summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy1
-rw-r--r--Auxiliary/vim/cmake.vim.in2
-rw-r--r--Auxiliary/vim/indent/cmake.vim2
-rw-r--r--Auxiliary/vim/syntax/cmake.vim7
-rw-r--r--CMakeCPack.cmake3
-rw-r--r--CMakeLists.txt9
-rw-r--r--CONTRIBUTING.rst2
-rw-r--r--CTestCustom.cmake.in32
-rw-r--r--Help/command/DEVICE_LINK_OPTIONS.txt2
-rw-r--r--Help/command/FIND_XXX.txt25
-rw-r--r--Help/command/LINK_OPTIONS_LINKER.txt3
-rw-r--r--Help/command/OPTIONS_SHELL.txt16
-rw-r--r--Help/command/add_custom_command.rst30
-rw-r--r--Help/command/build_command.rst16
-rw-r--r--Help/command/cmake_language.rst4
-rw-r--r--Help/command/cmake_minimum_required.rst23
-rw-r--r--Help/command/cmake_path.rst3
-rw-r--r--Help/command/configure_file.rst26
-rw-r--r--Help/command/ctest_build.rst8
-rw-r--r--Help/command/ctest_test.rst110
-rw-r--r--Help/command/enable_language.rst5
-rw-r--r--Help/command/file.rst107
-rw-r--r--Help/command/foreach.rst5
-rw-r--r--Help/command/install.rst162
-rw-r--r--Help/command/install_files.rst2
-rw-r--r--Help/command/install_programs.rst2
-rw-r--r--Help/command/install_targets.rst2
-rw-r--r--Help/command/list.rst4
-rw-r--r--Help/command/project.rst18
-rw-r--r--Help/command/set.rst10
-rw-r--r--Help/command/source_group.rst3
-rw-r--r--Help/command/target_link_libraries.rst85
-rw-r--r--Help/cpack_gen/archive.rst7
-rw-r--r--Help/cpack_gen/deb.rst2
-rw-r--r--Help/cpack_gen/dmg.rst8
-rw-r--r--Help/cpack_gen/freebsd.rst4
-rw-r--r--Help/cpack_gen/nsis.rst6
-rw-r--r--Help/cpack_gen/rpm.rst6
-rw-r--r--Help/dev/experimental.rst4
-rw-r--r--Help/dev/review.rst9
-rw-r--r--Help/envvar/CMAKE_LANG_LINKER_LAUNCHER.rst13
-rw-r--r--Help/envvar/CMAKE_TOOLCHAIN_FILE.rst12
-rw-r--r--Help/envvar/CUDAHOSTCXX.rst4
-rw-r--r--Help/envvar/HIPCXX.rst13
-rw-r--r--Help/envvar/HIPFLAGS.rst15
-rw-r--r--Help/generator/Ninja Multi-Config.rst4
-rw-r--r--Help/generator/VS_TOOLSET_HOST_ARCH.txt18
-rw-r--r--Help/generator/VS_TOOLSET_HOST_ARCH_LEGACY.txt11
-rw-r--r--Help/generator/Visual Studio 10 2010.rst5
-rw-r--r--Help/generator/Visual Studio 11 2012.rst5
-rw-r--r--Help/generator/Visual Studio 12 2013.rst7
-rw-r--r--Help/generator/Visual Studio 14 2015.rst7
-rw-r--r--Help/generator/Visual Studio 15 2017.rst7
-rw-r--r--Help/generator/Visual Studio 16 2019.rst5
-rw-r--r--Help/generator/Visual Studio 17 2022.rst62
-rw-r--r--Help/guide/importing-exporting/MathFunctions/CMakeLists.txt21
-rw-r--r--Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt14
-rw-r--r--Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt7
-rw-r--r--Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt14
-rw-r--r--Help/guide/importing-exporting/index.rst6
-rw-r--r--Help/guide/tutorial/A Basic Starting Point.rst151
-rw-r--r--Help/guide/tutorial/Adding Export Configuration.rst100
-rw-r--r--Help/guide/tutorial/Adding Generator Expressions.rst74
-rw-r--r--Help/guide/tutorial/Adding Support for a Testing Dashboard.rst61
-rw-r--r--Help/guide/tutorial/Adding System Introspection.rst58
-rw-r--r--Help/guide/tutorial/Adding Usage Requirements for a Library.rst52
-rw-r--r--Help/guide/tutorial/Adding a Custom Command and Generated File.rst85
-rw-r--r--Help/guide/tutorial/Adding a Library.rst130
-rw-r--r--Help/guide/tutorial/Installing and Testing.rst93
-rw-r--r--Help/guide/tutorial/Packaging Debug and Release.rst86
-rw-r--r--Help/guide/tutorial/Packaging an Installer.rst57
-rw-r--r--Help/guide/tutorial/Selecting Static or Shared Libraries.rst77
-rw-r--r--Help/guide/tutorial/Step12/CMakeLists.txt1
-rw-r--r--Help/guide/tutorial/index.rst973
-rw-r--r--Help/manual/OPTIONS_BUILD.txt8
-rw-r--r--Help/manual/cmake-compile-features.7.rst1
-rw-r--r--Help/manual/cmake-developer.7.rst18
-rw-r--r--Help/manual/cmake-env-variables.7.rst4
-rw-r--r--Help/manual/cmake-file-api.7.rst287
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst160
-rw-r--r--Help/manual/cmake-generators.7.rst1
-rw-r--r--Help/manual/cmake-modules.7.rst1
-rw-r--r--Help/manual/cmake-policies.7.rst13
-rw-r--r--Help/manual/cmake-presets.7.rst164
-rw-r--r--Help/manual/cmake-properties.7.rst6
-rw-r--r--Help/manual/cmake-toolchains.7.rst4
-rw-r--r--Help/manual/cmake-variables.7.rst7
-rw-r--r--Help/manual/cmake.1.rst17
-rw-r--r--Help/manual/ctest.1.rst75
-rw-r--r--Help/manual/presets/example.json15
-rw-r--r--Help/manual/presets/schema.json503
-rw-r--r--Help/module/FindMsys.rst1
-rw-r--r--Help/policy/CMP0102.rst4
-rw-r--r--Help/policy/CMP0104.rst2
-rw-r--r--Help/policy/CMP0110.rst2
-rw-r--r--Help/policy/CMP0121.rst21
-rw-r--r--Help/policy/CMP0122.rst17
-rw-r--r--Help/policy/CMP0123.rst32
-rw-r--r--Help/policy/CMP0124.rst20
-rw-r--r--Help/policy/CMP0125.rst25
-rw-r--r--Help/policy/CMP0126.rst22
-rw-r--r--Help/prop_dir/BUILDSYSTEM_TARGETS.rst2
-rw-r--r--Help/prop_dir/IMPORTED_TARGETS.rst14
-rw-r--r--Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst21
-rw-r--r--Help/prop_gbl/AUTOUIC_SOURCE_GROUP.rst9
-rw-r--r--Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst6
-rw-r--r--Help/prop_sf/COMPILE_FLAGS.rst7
-rw-r--r--Help/prop_sf/COMPILE_OPTIONS.rst7
-rw-r--r--Help/prop_sf/GENERATED.rst7
-rw-r--r--Help/prop_sf/LANGUAGE.rst4
-rw-r--r--Help/prop_test/FAIL_REGULAR_EXPRESSION.rst6
-rw-r--r--Help/prop_test/FIXTURES_REQUIRED.rst4
-rw-r--r--Help/prop_test/PASS_REGULAR_EXPRESSION.rst4
-rw-r--r--Help/prop_test/SKIP_REGULAR_EXPRESSION.rst4
-rw-r--r--Help/prop_tgt/COMPILE_OPTIONS.rst12
-rw-r--r--Help/prop_tgt/CUDA_ARCHITECTURES.rst2
-rw-r--r--Help/prop_tgt/CUDA_STANDARD.rst24
-rw-r--r--Help/prop_tgt/CXX_STANDARD.rst26
-rw-r--r--Help/prop_tgt/C_STANDARD.rst21
-rw-r--r--Help/prop_tgt/HIP_ARCHITECTURES.rst27
-rw-r--r--Help/prop_tgt/IMPORTED_OBJECTS.rst22
-rw-r--r--Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst2
-rw-r--r--Help/prop_tgt/LANG_LINKER_LAUNCHER.rst16
-rw-r--r--Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst5
-rw-r--r--Help/prop_tgt/LINK_OPTIONS.rst6
-rw-r--r--Help/prop_tgt/OBJCXX_STANDARD.rst22
-rw-r--r--Help/prop_tgt/OBJC_STANDARD.rst11
-rw-r--r--Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst2
-rw-r--r--Help/prop_tgt/Swift_MODULE_DIRECTORY.rst2
-rw-r--r--Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst2
-rw-r--r--Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst5
-rw-r--r--Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst6
-rw-r--r--Help/prop_tgt/XCODE_EMBED_type.rst20
-rw-r--r--Help/prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY.rst18
-rw-r--r--Help/prop_tgt/XCODE_EMBED_type_PATH.rst13
-rw-r--r--Help/prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY.rst20
-rw-r--r--Help/release/3.15.rst2
-rw-r--r--Help/release/3.16.rst2
-rw-r--r--Help/release/3.20.rst4
-rw-r--r--Help/release/3.21.rst295
-rw-r--r--Help/release/3.6.rst2
-rw-r--r--Help/release/index.rst1
-rw-r--r--Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst2
-rw-r--r--Help/variable/CMAKE_CFG_INTDIR.rst11
-rw-r--r--Help/variable/CMAKE_CONFIGURATION_TYPES.rst6
-rw-r--r--Help/variable/CMAKE_CUDA_HOST_COMPILER.rst4
-rw-r--r--Help/variable/CMAKE_GENERATOR_TOOLSET.rst24
-rw-r--r--Help/variable/CMAKE_HIP_ARCHITECTURES.rst11
-rw-r--r--Help/variable/CMAKE_LANG_COMPILER_ID.rst3
-rw-r--r--Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst2
-rw-r--r--Help/variable/CMAKE_LANG_FLAGS.rst8
-rw-r--r--Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst7
-rw-r--r--Help/variable/CMAKE_LANG_FLAGS_INIT.rst2
-rw-r--r--Help/variable/CMAKE_LANG_LINKER_LAUNCHER.rst11
-rw-r--r--Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst3
-rw-r--r--Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst2
-rw-r--r--Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst2
-rw-r--r--Help/variable/CMAKE_TLS_VERIFY.rst17
-rw-r--r--Help/variable/CMAKE_TOOLCHAIN_FILE.rst6
-rw-r--r--Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst13
-rw-r--r--Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst44
-rw-r--r--Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst3
-rw-r--r--Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst3
-rw-r--r--Help/variable/CTEST_SCRIPT_DIRECTORY.rst5
-rw-r--r--Help/variable/EXECUTABLE_OUTPUT_PATH.rst2
-rw-r--r--Help/variable/MSVC_VERSION.rst3
-rw-r--r--Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst21
-rw-r--r--Help/variable/PROJECT_IS_TOP_LEVEL.rst31
-rw-r--r--Modules/BasicConfigVersion-ExactVersion.cmake.in37
-rw-r--r--Modules/BasicConfigVersion-SameMajorVersion.cmake.in3
-rw-r--r--Modules/BasicConfigVersion-SameMinorVersion.cmake.in14
-rw-r--r--Modules/CMakeASM_NASMInformation.cmake11
-rw-r--r--Modules/CMakeCCompiler.cmake.in2
-rw-r--r--Modules/CMakeCCompilerId.c.in10
-rw-r--r--Modules/CMakeCInformation.cmake5
-rw-r--r--Modules/CMakeCUDAInformation.cmake58
-rw-r--r--Modules/CMakeCXXCompiler.cmake.in2
-rw-r--r--Modules/CMakeCXXCompilerId.cpp.in6
-rw-r--r--Modules/CMakeCXXInformation.cmake5
-rw-r--r--Modules/CMakeCheckCompilerFlagCommonPatterns.cmake2
-rw-r--r--Modules/CMakeCompilerIdDetection.cmake20
-rw-r--r--Modules/CMakeDependentOption.cmake5
-rw-r--r--Modules/CMakeDetermineCCompiler.cmake5
-rw-r--r--Modules/CMakeDetermineCUDACompiler.cmake17
-rw-r--r--Modules/CMakeDetermineCXXCompiler.cmake5
-rw-r--r--Modules/CMakeDetermineCompileFeatures.cmake74
-rw-r--r--Modules/CMakeDetermineCompiler.cmake10
-rw-r--r--Modules/CMakeDetermineCompilerId.cmake79
-rw-r--r--Modules/CMakeDetermineHIPCompiler.cmake101
-rw-r--r--Modules/CMakeDetermineSystem.cmake42
-rw-r--r--Modules/CMakeFindBinUtils.cmake89
-rw-r--r--Modules/CMakeFortranCompilerId.F.in11
-rw-r--r--Modules/CMakeHIPCompiler.cmake.in58
-rw-r--r--Modules/CMakeHIPCompilerABI.hip16
-rw-r--r--Modules/CMakeHIPCompilerId.hip.in54
-rw-r--r--Modules/CMakeHIPInformation.cmake139
-rw-r--r--Modules/CMakeHIPRuntime.cmake.in99
-rw-r--r--Modules/CMakeOBJCCompiler.cmake.in2
-rw-r--r--Modules/CMakeOBJCCompilerId.m.in4
-rw-r--r--Modules/CMakeOBJCInformation.cmake5
-rw-r--r--Modules/CMakeOBJCXXInformation.cmake5
-rw-r--r--Modules/CMakePackageConfigHelpers.cmake4
-rw-r--r--Modules/CMakeParseImplicitIncludeInfo.cmake65
-rw-r--r--Modules/CMakeParseImplicitLinkInfo.cmake32
-rw-r--r--Modules/CMakePlatformId.h.in11
-rw-r--r--Modules/CMakePrintHelpers.cmake5
-rw-r--r--Modules/CMakeSystemSpecificInformation.cmake1
-rw-r--r--Modules/CMakeTestHIPCompiler.cmake119
-rw-r--r--Modules/CPack.cmake25
-rw-r--r--Modules/CPackIFW.cmake10
-rw-r--r--Modules/CheckLinkerFlag.cmake2
-rw-r--r--Modules/Compiler/ARMClang.cmake89
-rw-r--r--Modules/Compiler/AppleClang-C.cmake12
-rw-r--r--Modules/Compiler/AppleClang-OBJC.cmake16
-rw-r--r--Modules/Compiler/CMakeCommonCompilerMacros.cmake22
-rw-r--r--Modules/Compiler/Clang-C.cmake59
-rw-r--r--Modules/Compiler/Clang-CUDA.cmake4
-rw-r--r--Modules/Compiler/Clang-HIP.cmake20
-rw-r--r--Modules/Compiler/Clang-OBJC.cmake12
-rw-r--r--Modules/Compiler/Clang.cmake3
-rw-r--r--Modules/Compiler/Fujitsu-C.cmake20
-rw-r--r--Modules/Compiler/Fujitsu-CXX.cmake47
-rw-r--r--Modules/Compiler/Fujitsu-DetermineCompiler.cmake17
-rw-r--r--Modules/Compiler/Fujitsu-Fortran.cmake16
-rw-r--r--Modules/Compiler/Fujitsu.cmake43
-rw-r--r--Modules/Compiler/FujitsuClang-C.cmake6
-rw-r--r--Modules/Compiler/FujitsuClang-CXX.cmake6
-rw-r--r--Modules/Compiler/FujitsuClang-DetermineCompiler.cmake9
-rw-r--r--Modules/Compiler/FujitsuClang-FindBinUtils.cmake6
-rw-r--r--Modules/Compiler/FujitsuClang.cmake11
-rw-r--r--Modules/Compiler/GNU-C.cmake12
-rw-r--r--Modules/Compiler/IAR.cmake14
-rw-r--r--Modules/Compiler/IntelLLVM-C.cmake10
-rw-r--r--Modules/Compiler/IntelLLVM-DetermineCompiler.cmake2
-rw-r--r--Modules/Compiler/NVIDIA-CUDA.cmake14
-rw-r--r--Modules/Compiler/OpenWatcom.cmake11
-rw-r--r--Modules/Compiler/ROCMClang-ASM.cmake2
-rw-r--r--Modules/Compiler/ROCMClang-C.cmake7
-rw-r--r--Modules/Compiler/ROCMClang-CXX.cmake7
-rw-r--r--Modules/Compiler/ROCMClang-DetermineCompiler.cmake19
-rw-r--r--Modules/Compiler/ROCMClang-FindBinUtils.cmake1
-rw-r--r--Modules/Compiler/ROCMClang-HIP.cmake49
-rw-r--r--Modules/Compiler/ROCMClang-OBJC.cmake7
-rw-r--r--Modules/Compiler/ROCMClang-OBJCXX.cmake7
-rw-r--r--Modules/Compiler/ROCMClang.cmake35
-rw-r--r--Modules/Compiler/TI.cmake9
-rw-r--r--Modules/ExternalData.cmake16
-rw-r--r--Modules/ExternalProject.cmake25
-rw-r--r--Modules/FetchContent.cmake59
-rw-r--r--Modules/FindBLAS.cmake394
-rw-r--r--Modules/FindBoost.cmake2
-rw-r--r--Modules/FindCUDA.cmake12
-rw-r--r--Modules/FindCUDAToolkit.cmake13
-rw-r--r--Modules/FindCurses.cmake2
-rw-r--r--Modules/FindDevIL.cmake100
-rw-r--r--Modules/FindDoxygen.cmake4
-rw-r--r--Modules/FindFLTK.cmake2
-rw-r--r--Modules/FindGettext.cmake4
-rw-r--r--Modules/FindGnuplot.cmake2
-rw-r--r--Modules/FindHDF5.cmake67
-rw-r--r--Modules/FindIconv.cmake84
-rw-r--r--Modules/FindIntl.cmake54
-rw-r--r--Modules/FindJNI.cmake2
-rw-r--r--Modules/FindLAPACK.cmake267
-rw-r--r--Modules/FindLATEX.cmake4
-rw-r--r--Modules/FindMPI.cmake7
-rw-r--r--Modules/FindMatlab.cmake18
-rw-r--r--Modules/FindMsys.cmake31
-rw-r--r--Modules/FindOpenMP.cmake6
-rw-r--r--Modules/FindOpenSSL.cmake4
-rw-r--r--Modules/FindPerl.cmake2
-rw-r--r--Modules/FindPkgConfig.cmake4
-rw-r--r--Modules/FindProtobuf.cmake8
-rw-r--r--Modules/FindRuby.cmake2
-rw-r--r--Modules/FindSWIG.cmake94
-rw-r--r--Modules/FindSelfPackers.cmake3
-rw-r--r--Modules/FindThreads.cmake16
-rw-r--r--Modules/FindUnixCommands.cmake7
-rw-r--r--Modules/FindVulkan.cmake54
-rw-r--r--Modules/FindWget.cmake2
-rw-r--r--Modules/FortranCInterface/Detect.cmake19
-rw-r--r--Modules/GNUInstallDirs.cmake5
-rw-r--r--Modules/GetPrerequisites.cmake2
-rw-r--r--Modules/GoogleTest.cmake3
-rw-r--r--Modules/Internal/CPack/CPackDeb.cmake4
-rw-r--r--Modules/Internal/CPack/CPackRPM.cmake111
-rw-r--r--Modules/Internal/CPack/NSIS.template.in4
-rw-r--r--Modules/Internal/CheckCompilerFlag.cmake9
-rw-r--r--Modules/Internal/CheckSourceCompiles.cmake3
-rw-r--r--Modules/Internal/CheckSourceRuns.cmake3
-rw-r--r--Modules/Internal/FeatureTesting.cmake14
-rw-r--r--Modules/Platform/ARTOS-GNU-C.cmake2
-rw-r--r--Modules/Platform/Android-Initialize.cmake5
-rw-r--r--Modules/Platform/Apple-NVIDIA-CUDA.cmake12
-rw-r--r--Modules/Platform/CYGWIN-GNU.cmake2
-rw-r--r--Modules/Platform/CYGWIN.cmake4
-rw-r--r--Modules/Platform/Darwin.cmake4
-rw-r--r--Modules/Platform/Linux-Fujitsu-C.cmake1
-rw-r--r--Modules/Platform/Linux-Fujitsu-CXX.cmake1
-rw-r--r--Modules/Platform/Linux-Fujitsu.cmake17
-rw-r--r--Modules/Platform/MSYS-Clang-C.cmake1
-rw-r--r--Modules/Platform/MSYS-Clang-CXX.cmake1
-rw-r--r--Modules/Platform/MSYS-Determine-CXX.cmake1
-rw-r--r--Modules/Platform/MSYS-GNU-C.cmake1
-rw-r--r--Modules/Platform/MSYS-GNU-CXX.cmake1
-rw-r--r--Modules/Platform/MSYS-GNU-Fortran.cmake1
-rw-r--r--Modules/Platform/MSYS-GNU.cmake1
-rw-r--r--Modules/Platform/MSYS-windres.cmake1
-rw-r--r--Modules/Platform/MSYS.cmake4
-rw-r--r--Modules/Platform/Windows-Clang.cmake8
-rw-r--r--Modules/Platform/Windows-Embarcadero.cmake8
-rw-r--r--Modules/Platform/Windows-GNU.cmake4
-rw-r--r--Modules/Platform/Windows-Intel.cmake4
-rw-r--r--Modules/Platform/Windows-MSVC.cmake12
-rw-r--r--Modules/Platform/Windows-NVIDIA-CUDA.cmake42
-rw-r--r--Modules/Platform/Windows-OpenWatcom-C.cmake1
-rw-r--r--Modules/Platform/Windows-OpenWatcom-CXX.cmake1
-rw-r--r--Modules/Platform/Windows-OpenWatcom.cmake7
-rw-r--r--Modules/Platform/Windows-df.cmake4
-rw-r--r--Modules/UseJava.cmake856
-rw-r--r--Modules/UseSWIG.cmake44
-rw-r--r--Modules/WriteCompilerDetectionHeader.cmake1
-rw-r--r--Source/CMakeLists.txt15
-rw-r--r--Source/CMakeVersion.cmake6
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.cxx111
-rw-r--r--Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx6
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx39
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.h2
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx6
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx9
-rw-r--r--Source/CPack/cmCPackGenerator.cxx22
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx4
-rw-r--r--Source/CPack/cmCPackSTGZGenerator.cxx13
-rw-r--r--Source/CPack/cpack.cxx2
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx4
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx5
-rw-r--r--Source/CTest/cmCTestBuildCommand.h1
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx5
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx7
-rw-r--r--Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx2
-rw-r--r--Source/CTest/cmCTestGenericHandler.cxx52
-rw-r--r--Source/CTest/cmCTestGenericHandler.h34
-rw-r--r--Source/CTest/cmCTestMemCheckCommand.cxx2
-rw-r--r--Source/CTest/cmCTestMemCheckCommand.h3
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx10
-rw-r--r--Source/CTest/cmCTestRunScriptCommand.cxx4
-rw-r--r--Source/CTest/cmCTestRunTest.cxx16
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx25
-rw-r--r--Source/CTest/cmCTestScriptHandler.h12
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx16
-rw-r--r--Source/CTest/cmCTestTestCommand.h4
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx357
-rw-r--r--Source/CTest/cmCTestTestHandler.h22
-rw-r--r--Source/CTest/cmCTestUpdateCommand.cxx1
-rw-r--r--Source/Checks/cm_cxx_features.cmake4
-rw-r--r--Source/CursesDialog/ccmake.cxx5
-rw-r--r--Source/CursesDialog/form/CMakeLists.txt2
-rw-r--r--Source/LexerParser/cmCTestResourceGroupsLexer.cxx2
-rw-r--r--Source/LexerParser/cmCTestResourceGroupsLexer.in.l2
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.cxx2
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.in.l2
-rw-r--r--Source/LexerParser/cmCommandArgumentParser.cxx86
-rw-r--r--Source/LexerParser/cmCommandArgumentParserTokens.h4
-rw-r--r--Source/LexerParser/cmDependsJavaLexer.cxx2
-rw-r--r--Source/LexerParser/cmDependsJavaLexer.in.l2
-rw-r--r--Source/LexerParser/cmDependsJavaParser.cxx716
-rw-r--r--Source/LexerParser/cmDependsJavaParserTokens.h4
-rw-r--r--Source/LexerParser/cmExprLexer.cxx2
-rw-r--r--Source/LexerParser/cmExprLexer.in.l2
-rw-r--r--Source/LexerParser/cmExprParser.cxx146
-rw-r--r--Source/LexerParser/cmExprParser.y4
-rw-r--r--Source/LexerParser/cmExprParserTokens.h4
-rw-r--r--Source/LexerParser/cmFortranLexer.cxx2
-rw-r--r--Source/LexerParser/cmFortranLexer.in.l2
-rw-r--r--Source/LexerParser/cmFortranParser.cxx170
-rw-r--r--Source/LexerParser/cmFortranParser.y2
-rw-r--r--Source/LexerParser/cmFortranParserTokens.h4
-rw-r--r--Source/LexerParser/cmGccDepfileLexer.cxx2
-rw-r--r--Source/LexerParser/cmGccDepfileLexer.in.l2
-rw-r--r--Source/Modules/FindLibUUID.cmake9
-rw-r--r--Source/QtDialog/CMakeSetup.cxx11
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx4
-rw-r--r--Source/QtDialog/QCMake.cxx16
-rw-r--r--Source/cmArchiveWrite.cxx48
-rw-r--r--Source/cmArchiveWrite.h3
-rw-r--r--Source/cmBinUtilsLinuxELFLinker.cxx43
-rw-r--r--Source/cmBinUtilsLinuxELFLinker.h4
-rw-r--r--Source/cmBinUtilsMacOSMachOLinker.cxx22
-rw-r--r--Source/cmBinUtilsMacOSMachOLinker.h2
-rw-r--r--Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx5
-rw-r--r--Source/cmBuildCommand.cxx13
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx16
-rw-r--r--Source/cmCMakePathCommand.cxx5
-rw-r--r--Source/cmCMakePresetsFile.cxx1082
-rw-r--r--Source/cmCMakePresetsFile.h29
-rw-r--r--Source/cmCMakePresetsFileInternal.h112
-rw-r--r--Source/cmCMakePresetsFileReadJSON.cxx1032
-rw-r--r--Source/cmCPluginAPI.cxx2
-rw-r--r--Source/cmCTest.cxx97
-rw-r--r--Source/cmCTest.h5
-rw-r--r--Source/cmCommandLineArgument.h107
-rw-r--r--Source/cmCommonTargetGenerator.cxx25
-rw-r--r--Source/cmCommonTargetGenerator.h2
-rw-r--r--Source/cmComputeLinkDepends.cxx50
-rw-r--r--Source/cmComputeLinkDepends.h6
-rw-r--r--Source/cmComputeLinkInformation.cxx67
-rw-r--r--Source/cmComputeLinkInformation.h39
-rw-r--r--Source/cmComputeTargetDepends.cxx62
-rw-r--r--Source/cmComputeTargetDepends.h3
-rw-r--r--Source/cmConditionEvaluator.cxx4
-rw-r--r--Source/cmCoreTryCompile.cxx44
-rw-r--r--Source/cmCreateTestSourceList.cxx11
-rw-r--r--Source/cmCustomCommand.cxx10
-rw-r--r--Source/cmCustomCommand.h5
-rw-r--r--Source/cmCustomCommandGenerator.cxx81
-rw-r--r--Source/cmCustomCommandGenerator.h15
-rw-r--r--Source/cmDepends.cxx3
-rw-r--r--Source/cmDependsC.cxx7
-rw-r--r--Source/cmDependsCompiler.cxx14
-rw-r--r--Source/cmDependsFortran.cxx35
-rw-r--r--Source/cmDependsFortran.h4
-rw-r--r--Source/cmELF.cxx16
-rw-r--r--Source/cmELF.h4
-rw-r--r--Source/cmExportFileGenerator.cxx6
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx5
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx14
-rw-r--r--Source/cmExtraKateGenerator.cxx2
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx3
-rw-r--r--Source/cmFileAPI.cxx2
-rw-r--r--Source/cmFileAPICodemodel.cxx518
-rw-r--r--Source/cmFileCommand.cxx432
-rw-r--r--Source/cmFindBase.cxx164
-rw-r--r--Source/cmFindBase.h17
-rw-r--r--Source/cmFindFileCommand.cxx5
-rw-r--r--Source/cmFindLibraryCommand.cxx51
-rw-r--r--Source/cmFindPackageCommand.cxx5
-rw-r--r--Source/cmFindPathCommand.cxx51
-rw-r--r--Source/cmFindPathCommand.h1
-rw-r--r--Source/cmFindProgramCommand.cxx47
-rw-r--r--Source/cmForEachCommand.cxx37
-rw-r--r--Source/cmGeneratedFileStream.cxx5
-rw-r--r--Source/cmGeneratorExpressionNode.cxx64
-rw-r--r--Source/cmGeneratorTarget.cxx362
-rw-r--r--Source/cmGeneratorTarget.h24
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx10
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx2
-rw-r--r--Source/cmGlobalGenerator.cxx39
-rw-r--r--Source/cmGlobalGenerator.h17
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx8
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h2
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx39
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h7
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx255
-rw-r--r--Source/cmGlobalNinjaGenerator.h36
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx47
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx367
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h35
-rw-r--r--Source/cmGlobalVisualStudio11Generator.h7
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx3
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx11
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h3
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx129
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.h7
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx169
-rw-r--r--Source/cmGlobalXCodeGenerator.h28
-rw-r--r--Source/cmInstallCommand.cxx600
-rw-r--r--Source/cmInstallDirectoryGenerator.cxx2
-rw-r--r--Source/cmInstallExportGenerator.cxx7
-rw-r--r--Source/cmInstallFilesGenerator.cxx2
-rw-r--r--Source/cmInstallGenerator.cxx132
-rw-r--r--Source/cmInstallGenerator.h24
-rw-r--r--Source/cmInstallGetRuntimeDependenciesGenerator.cxx206
-rw-r--r--Source/cmInstallGetRuntimeDependenciesGenerator.h56
-rw-r--r--Source/cmInstallImportedRuntimeArtifactsGenerator.cxx146
-rw-r--r--Source/cmInstallImportedRuntimeArtifactsGenerator.h44
-rw-r--r--Source/cmInstallRuntimeDependencySet.cxx95
-rw-r--r--Source/cmInstallRuntimeDependencySet.h163
-rw-r--r--Source/cmInstallRuntimeDependencySetGenerator.cxx276
-rw-r--r--Source/cmInstallRuntimeDependencySetGenerator.h74
-rw-r--r--Source/cmInstallScriptGenerator.cxx5
-rw-r--r--Source/cmInstallScriptGenerator.h2
-rw-r--r--Source/cmInstallSubdirectoryGenerator.cxx2
-rw-r--r--Source/cmInstallTargetGenerator.cxx76
-rw-r--r--Source/cmInstallTargetGenerator.h11
-rw-r--r--Source/cmJSONHelpers.h2
-rw-r--r--Source/cmLinkItem.h11
-rw-r--r--Source/cmLinkLineComputer.cxx18
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx2
-rw-r--r--Source/cmListCommand.cxx68
-rw-r--r--Source/cmListFileCache.cxx17
-rw-r--r--Source/cmLoadCommandCommand.cxx9
-rw-r--r--Source/cmLocalCommonGenerator.cxx29
-rw-r--r--Source/cmLocalCommonGenerator.h16
-rw-r--r--Source/cmLocalGenerator.cxx100
-rw-r--r--Source/cmLocalGenerator.h41
-rw-r--r--Source/cmLocalNinjaGenerator.cxx76
-rw-r--r--Source/cmLocalNinjaGenerator.h7
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx86
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx19
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx6
-rw-r--r--Source/cmMakefile.cxx53
-rw-r--r--Source/cmMakefile.h3
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx79
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx87
-rw-r--r--Source/cmMakefileTargetGenerator.cxx139
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.cxx6
-rw-r--r--Source/cmMessageMetadata.h11
-rw-r--r--Source/cmMessenger.cxx26
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx47
-rw-r--r--Source/cmNinjaTargetGenerator.cxx68
-rw-r--r--Source/cmNinjaTargetGenerator.h9
-rw-r--r--Source/cmNinjaTypes.h1
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx17
-rw-r--r--Source/cmOptionCommand.cxx7
-rw-r--r--Source/cmOrderDirectories.cxx4
-rw-r--r--Source/cmOutputConverter.cxx94
-rw-r--r--Source/cmOutputConverter.h32
-rw-r--r--Source/cmPolicies.h22
-rw-r--r--Source/cmProjectCommand.cxx9
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx5
-rw-r--r--Source/cmQtAutoGenInitializer.cxx238
-rw-r--r--Source/cmQtAutoGenInitializer.h13
-rw-r--r--Source/cmQtAutoGenerator.cxx2
-rw-r--r--Source/cmQtAutoMocUic.cxx12
-rw-r--r--Source/cmRulePlaceholderExpander.cxx20
-rw-r--r--Source/cmRulePlaceholderExpander.h1
-rw-r--r--Source/cmRuntimeDependencyArchive.cxx109
-rw-r--r--Source/cmRuntimeDependencyArchive.h34
-rw-r--r--Source/cmScanDepFormat.cxx252
-rw-r--r--Source/cmScanDepFormat.h21
-rw-r--r--Source/cmSourceFile.h2
-rw-r--r--Source/cmStandardLevelResolver.cxx32
-rw-r--r--Source/cmStandardLexer.h5
-rw-r--r--Source/cmState.cxx1
-rw-r--r--Source/cmStateDirectory.cxx127
-rw-r--r--Source/cmStateDirectory.h15
-rw-r--r--Source/cmStatePrivate.h9
-rw-r--r--Source/cmStateSnapshot.cxx55
-rw-r--r--Source/cmStringCommand.cxx4
-rw-r--r--Source/cmSystemTools.cxx447
-rw-r--r--Source/cmSystemTools.h69
-rw-r--r--Source/cmTarget.cxx20
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx2
-rw-r--r--Source/cmTransformDepfile.cxx89
-rw-r--r--Source/cmTransformDepfile.h3
-rw-r--r--Source/cmUVHandlePtr.cxx2
-rw-r--r--Source/cmVSSetupHelper.cxx8
-rw-r--r--Source/cmVSSetupHelper.h4
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx105
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h8
-rw-r--r--Source/cmVisualStudio10ToolsetOptions.cxx143
-rw-r--r--Source/cmVisualStudio10ToolsetOptions.h31
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx11
-rw-r--r--Source/cmWorkingDirectory.cxx2
-rw-r--r--Source/cmXCodeScheme.cxx2
-rw-r--r--Source/cm_codecvt.cxx1
-rw-r--r--Source/cm_codecvt.hxx1
-rw-r--r--Source/cmake.cxx197
-rw-r--r--Source/cmake.h26
-rw-r--r--Source/cmakemain.cxx38
-rw-r--r--Source/cmcmd.cxx82
-rw-r--r--Source/cmcmd.h6
-rw-r--r--Source/ctest.cxx11
-rw-r--r--Source/kwsys/CMakeLists.txt16
-rw-r--r--Source/kwsys/Directory.cxx39
-rw-r--r--Source/kwsys/Directory.hxx.in6
-rw-r--r--Source/kwsys/EncodingC.c2
-rw-r--r--Source/kwsys/Glob.hxx.in7
-rw-r--r--Source/kwsys/ProcessUNIX.c12
-rw-r--r--Source/kwsys/Status.cxx60
-rw-r--r--Source/kwsys/Status.hxx.in101
-rw-r--r--Source/kwsys/SystemInformation.cxx23
-rw-r--r--Source/kwsys/SystemTools.cxx418
-rw-r--r--Source/kwsys/SystemTools.hxx.in68
-rw-r--r--Source/kwsys/Terminal.c10
-rw-r--r--Source/kwsys/testDirectory.cxx4
-rw-r--r--Source/kwsys/testDynamicLoader.cxx23
-rw-r--r--Source/kwsys/testStatus.cxx117
-rw-r--r--Source/kwsys/testSystemTools.cxx47
-rw-r--r--Templates/MSBuild/CustomBuildDepFile.targets48
-rw-r--r--Templates/MSBuild/FlagTables/v10_CSharp.json51
-rw-r--r--Templates/MSBuild/FlagTables/v10_Link.json9
-rw-r--r--Templates/MSBuild/FlagTables/v11_CSharp.json51
-rw-r--r--Templates/MSBuild/FlagTables/v11_Link.json9
-rw-r--r--Templates/MSBuild/FlagTables/v12_CSharp.json51
-rw-r--r--Templates/MSBuild/FlagTables/v12_Link.json9
-rw-r--r--Templates/MSBuild/FlagTables/v140_CSharp.json51
-rw-r--r--Templates/MSBuild/FlagTables/v140_Link.json9
-rw-r--r--Templates/MSBuild/FlagTables/v141_CL.json53
-rw-r--r--Templates/MSBuild/FlagTables/v141_CSharp.json51
-rw-r--r--Templates/MSBuild/FlagTables/v141_Link.json9
-rw-r--r--Templates/MSBuild/FlagTables/v142_CL.json253
-rw-r--r--Templates/MSBuild/FlagTables/v142_CSharp.json51
-rw-r--r--Templates/MSBuild/FlagTables/v142_Link.json9
-rw-r--r--Templates/TestDriver.cxx.in45
-rw-r--r--Tests/BundleGeneratorTest/CMakeLists.txt2
-rw-r--r--Tests/CMakeCommands/target_link_libraries/CMakeLists.txt2
-rw-r--r--Tests/CMakeCommands/target_link_libraries/SubDirA/CMakeLists.txt4
-rw-r--r--Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt4
-rw-r--r--Tests/CMakeCommands/target_link_libraries/TopDir.c6
-rw-r--r--Tests/CMakeLib/testOptional.cxx2
-rw-r--r--Tests/CMakeLib/testString.cxx4
-rw-r--r--Tests/CMakeLib/testVisualStudioSlnParser.cxx2
-rw-r--r--Tests/CMakeLists.txt70
-rw-r--r--Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt2
-rw-r--r--Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt2
-rw-r--r--Tests/CMakeOnly/CheckLanguage/CMakeLists.txt2
-rw-r--r--Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt2
-rw-r--r--Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt2
-rw-r--r--Tests/CMakeOnly/TargetScope/CMakeLists.txt2
-rw-r--r--Tests/CMakeTests/CMakeLists.txt1
-rw-r--r--Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in26
-rw-r--r--Tests/CPackComponents/CMakeLists.txt2
-rw-r--r--Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake2
-rw-r--r--Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in2
-rw-r--r--Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake19
-rw-r--r--Tests/CSharpOnly/CMakeLists.txt7
-rw-r--r--Tests/CSharpOnly/config_specific_main_debug.cs10
-rw-r--r--Tests/CSharpOnly/config_specific_main_no_exist.cs10
-rw-r--r--Tests/CSharpOnly/config_specific_main_not_debug.cs10
-rw-r--r--Tests/CTestTest2/test.cmake.in2
-rw-r--r--Tests/CTestTestBadExe/test.cmake.in2
-rw-r--r--Tests/CTestTestChecksum/test.cmake.in2
-rw-r--r--Tests/CTestTestCostSerial/test.cmake.in2
-rw-r--r--Tests/CTestTestCrash/CMakeLists.txt2
-rw-r--r--Tests/CTestTestCrash/test.cmake.in2
-rw-r--r--Tests/CTestTestCycle/CMakeLists.txt2
-rw-r--r--Tests/CTestTestCycle/test.cmake.in2
-rw-r--r--Tests/CTestTestDepends/CMakeLists.txt2
-rw-r--r--Tests/CTestTestDepends/test.cmake.in2
-rw-r--r--Tests/CTestTestFailure/CMakeLists.txt2
-rw-r--r--Tests/CTestTestFailure/testNoBuild.cmake.in2
-rw-r--r--Tests/CTestTestFailure/testNoExe.cmake.in2
-rw-r--r--Tests/CTestTestLabelRegExp/test.cmake.in4
-rw-r--r--Tests/CTestTestParallel/CMakeLists.txt2
-rw-r--r--Tests/CTestTestParallel/test.cmake.in2
-rw-r--r--Tests/CTestTestResourceLock/CMakeLists.txt2
-rw-r--r--Tests/CTestTestResourceLock/test.cmake.in2
-rw-r--r--Tests/CTestTestScheduler/CMakeLists.txt2
-rw-r--r--Tests/CTestTestScheduler/test.cmake.in2
-rw-r--r--Tests/CTestTestSkipReturnCode/test.cmake.in2
-rw-r--r--Tests/CTestTestStopTime/CMakeLists.txt2
-rw-r--r--Tests/CTestTestStopTime/test.cmake.in2
-rw-r--r--Tests/CTestTestSubdir/CMakeLists.txt2
-rw-r--r--Tests/CTestTestSubdir/test.cmake.in2
-rw-r--r--Tests/CTestTestTimeout/test.cmake.in2
-rw-r--r--Tests/CTestTestUpload/CMakeLists.txt2
-rw-r--r--Tests/CTestTestUpload/test.cmake.in2
-rw-r--r--Tests/CTestTestVerboseOutput/CMakeLists.txt2
-rw-r--r--Tests/CTestTestVerboseOutput/test.cmake.in2
-rw-r--r--Tests/CTestTestZeroTimeout/CMakeLists.txt2
-rw-r--r--Tests/CTestTestZeroTimeout/test.cmake.in2
-rw-r--r--Tests/CheckFortran.cmake2
-rw-r--r--Tests/CompileFeatures/CMakeLists.txt6
-rw-r--r--Tests/CompileFeatures/cxx_contextual_conversions.cpp2
-rw-r--r--Tests/CompileFeatures/default_dialect.c10
-rw-r--r--Tests/CompileOptions/CMakeLists.txt28
-rw-r--r--Tests/CompileOptions/main.cpp18
-rw-r--r--Tests/ConfigSources/CMakeLists.txt5
-rw-r--r--Tests/CustomCommand/CMakeLists.txt4
-rw-r--r--Tests/CustomCommandWorkingDirectory/CMakeLists.txt2
-rw-r--r--Tests/Dependency/CMakeLists.txt2
-rw-r--r--Tests/ExportImport/CMakeLists.txt36
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt8
-rw-r--r--Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt42
-rw-r--r--Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/deplib.c12
-rw-r--r--Tests/ExportImport/Import/CMakeLists.txt9
-rw-r--r--Tests/ExportImport/Import/Interface/pch_iface_test.cpp3
-rw-r--r--Tests/ExportImport/Import/check_installed.cmake20
-rw-r--r--Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/CMakeLists.txt30
-rw-r--r--Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake38
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/CMakeLists.txt74
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/check_installed.cmake11
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/lib.c12
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/main.c31
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/mod.c12
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib1.c12
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib2.c12
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt33
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/check_installed.cmake11
-rw-r--r--Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/main.c15
-rw-r--r--Tests/ExternalProjectLocal/CMakeLists.txt6
-rw-r--r--Tests/FindBLAS/CMakeLists.txt59
-rw-r--r--Tests/FindBLAS/Test/CMakeLists.txt7
-rw-r--r--Tests/FindDevIL/CMakeLists.txt10
-rw-r--r--Tests/FindDevIL/Test/CMakeLists.txt29
-rw-r--r--Tests/FindDevIL/Test/main.c10
-rw-r--r--Tests/FindDevIL/Test/main_ilu.c8
-rw-r--r--Tests/FindLAPACK/CMakeLists.txt59
-rw-r--r--Tests/FindLAPACK/Test/CMakeLists.txt7
-rw-r--r--Tests/FindPackageModeMakefileTest/CMakeLists.txt16
-rw-r--r--Tests/FindPackageModeMakefileTest/Makefile.in6
-rw-r--r--Tests/FindPackageTest/CMakeLists.txt6
-rw-r--r--Tests/FindProtobuf/CMakeLists.txt1
-rw-r--r--Tests/FindProtobuf/Test/CMakeLists.txt13
-rw-r--r--Tests/FindProtobuf/Test/main-generate-grpc.cxx6
-rw-r--r--Tests/FindProtobuf/Test/msgs/example_service.proto8
-rw-r--r--Tests/FindVulkan/Test/CMakeLists.txt20
-rw-r--r--Tests/FindVulkan/Test/Run-glslangValidator.cmake20
-rw-r--r--Tests/FindVulkan/Test/main-dynamicVulkanLoading.cpp55
-rw-r--r--Tests/Fortran/CMakeLists.txt4
-rw-r--r--Tests/FortranModules/CMakeLists.txt5
-rw-r--r--Tests/FortranOnly/CMakeLists.txt26
-rw-r--r--Tests/Framework/CMakeLists.txt4
-rw-r--r--Tests/FunctionTest/CMakeLists.txt2
-rw-r--r--Tests/HIP/ArchitectureOff/CMakeLists.txt8
-rw-r--r--Tests/HIP/ArchitectureOff/main.hip9
-rw-r--r--Tests/HIP/CMakeLists.txt15
-rw-r--r--Tests/HIP/CompileFlags/CMakeLists.txt8
-rw-r--r--Tests/HIP/CompileFlags/main.hip13
-rw-r--r--Tests/HIP/EnableStandard/CMakeLists.txt20
-rw-r--r--Tests/HIP/EnableStandard/main.hip23
-rw-r--r--Tests/HIP/EnableStandard/shared.hip15
-rw-r--r--Tests/HIP/EnableStandard/static.cxx9
-rw-r--r--Tests/HIP/InferHipLang1/CMakeLists.txt12
-rw-r--r--Tests/HIP/InferHipLang1/interface.hip19
-rw-r--r--Tests/HIP/InferHipLang1/main.cxx19
-rw-r--r--Tests/HIP/InferHipLang2/CMakeLists.txt12
-rw-r--r--Tests/HIP/InferHipLang2/interface.hip19
-rw-r--r--Tests/HIP/InferHipLang2/main.cxx19
-rw-r--r--Tests/HIP/MathFunctions/CMakeLists.txt18
-rw-r--r--Tests/HIP/MathFunctions/main.hip40
-rw-r--r--Tests/HIP/MixedLanguage/CMakeLists.txt19
-rw-r--r--Tests/HIP/MixedLanguage/main.cxx40
-rw-r--r--Tests/HIP/MixedLanguage/shared.c12
-rw-r--r--Tests/HIP/MixedLanguage/shared.cxx21
-rw-r--r--Tests/HIP/MixedLanguage/shared.hip26
-rw-r--r--Tests/HIP/MixedLanguage/static.c6
-rw-r--r--Tests/HIP/MixedLanguage/static.cxx7
-rw-r--r--Tests/HIP/MixedLanguage/static.hip21
-rw-r--r--Tests/HIP/TryCompile/CMakeLists.txt15
-rw-r--r--Tests/HIP/TryCompile/device_function.hip17
-rw-r--r--Tests/HIP/TryCompile/main.hip8
-rw-r--r--Tests/HIP/WithDefs/CMakeLists.txt37
-rw-r--r--Tests/HIP/WithDefs/inc_hip/inc_hip.h1
-rw-r--r--Tests/HIP/WithDefs/main.hip.cpp89
-rw-r--r--Tests/JCTest/CMakeLists.txt2
-rw-r--r--Tests/Java/CMakeLists.txt9
-rw-r--r--Tests/Java/HelloWorld.txt1
-rw-r--r--Tests/Java/ResourceNS.java48
-rw-r--r--Tests/JavaJavah/CMakeLists.txt2
-rw-r--r--Tests/JavaNativeHeaders/CMakeLists.txt2
-rw-r--r--Tests/LibName/CMakeLists.txt8
-rw-r--r--Tests/LibName/use_ver_space.c9
-rw-r--r--Tests/LibName/ver_space.c7
-rw-r--r--Tests/LoadCommand/CMakeCommands/CMakeLists.txt2
-rw-r--r--Tests/LoadCommand/CMakeLists.txt2
-rw-r--r--Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt2
-rw-r--r--Tests/LoadCommandOneConfig/CMakeLists.txt2
-rw-r--r--Tests/MakeClean/CMakeLists.txt2
-rw-r--r--Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt4
-rw-r--r--Tests/ModuleDefinition/CMakeLists.txt2
-rw-r--r--Tests/NewlineArgs/CMakeLists.txt2
-rw-r--r--Tests/ObjectLibrary/CMakeLists.txt2
-rw-r--r--Tests/ObjectLibrary/LinkObjects/CMakeLists.txt45
-rw-r--r--Tests/ObjectLibrary/LinkObjects/a_dep.c7
-rw-r--r--Tests/ObjectLibrary/LinkObjects/a_obj.c8
-rw-r--r--Tests/ObjectLibrary/LinkObjects/b_dep.c7
-rw-r--r--Tests/ObjectLibrary/LinkObjects/b_obj.c8
-rw-r--r--Tests/ObjectLibrary/LinkObjects/c_dep.c7
-rw-r--r--Tests/ObjectLibrary/LinkObjects/c_obj.c8
-rw-r--r--Tests/ObjectLibrary/LinkObjects/d_dep.c7
-rw-r--r--Tests/ObjectLibrary/LinkObjects/d_obj.c8
-rw-r--r--Tests/ObjectLibrary/LinkObjects/e_dep.c7
-rw-r--r--Tests/ObjectLibrary/LinkObjects/e_lib.c5
-rw-r--r--Tests/ObjectLibrary/LinkObjects/e_obj.c8
-rw-r--r--Tests/ObjectLibrary/LinkObjects/main.c24
-rw-r--r--Tests/Plugin/CMakeLists.txt4
-rw-r--r--Tests/PositionIndependentTargets/interface/CMakeLists.txt3
-rw-r--r--Tests/Preprocess/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt102
-rw-r--r--Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in11
-rw-r--r--Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp9
-rw-r--r--Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.ui.in7
-rw-r--r--Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mocwidget.h5
-rw-r--r--Tests/QtAutogen/TestMacros.cmake1
-rw-r--r--Tests/QtAutogen/Tests.cmake4
-rw-r--r--Tests/QtAutogen/WrappedFindPackage/CMakeLists.txt16
-rw-r--r--Tests/QtAutogen/WrappedFindPackage/main.cpp19
-rw-r--r--Tests/ReturnTest/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake8
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake19
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake3
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake3
-rw-r--r--Tests/RunCMake/BuildDepends/RunCMakeTest.cmake28
-rw-r--r--Tests/RunCMake/BundleUtilities/CMP0080-COMMAND-OLD-stderr.txt9
-rw-r--r--Tests/RunCMake/BundleUtilities/CMP0080-OLD-stderr.txt10
-rw-r--r--Tests/RunCMake/CMP0041/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/CMP0081/CMP0081-OLD-result.txt1
-rw-r--r--Tests/RunCMake/CMP0081/CMP0081-OLD-stderr.txt10
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-Common.cmake8
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt18
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-GET-Common.cmake4
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-GET-NEW-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-GET-NEW-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-GET-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-GET-OLD-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-GET-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-GET-WARN-stderr.txt11
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-GET-WARN.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-INSERT-Common.cmake4
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN-stderr.txt11
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-Common.cmake4
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN-stderr.txt11
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-Common.cmake4
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN-stderr.txt11
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-Common.cmake4
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN-stderr.txt11
-rw-r--r--Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN.cmake2
-rw-r--r--Tests/RunCMake/CMP0121/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0121/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_file-Common.cmake51
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_file-NEW-stderr.txt14
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_file-NEW.cmake4
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_file-OLD-stderr.txt14
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_file-OLD.cmake4
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_library-Common.cmake52
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_library-NEW-stderr.txt14
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_library-NEW.cmake6
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_library-OLD-stderr.txt14
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_library-OLD.cmake6
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_path-Common.cmake51
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_path-NEW-stderr.txt14
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_path-NEW.cmake4
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_path-OLD-stderr.txt14
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_path-OLD.cmake4
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_program-Common.cmake52
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_program-NEW-stderr.txt14
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_program-NEW.cmake4
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_program-OLD-stderr.txt14
-rw-r--r--Tests/RunCMake/CMP0125/CMP0125-find_program-OLD.cmake4
-rw-r--r--Tests/RunCMake/CMP0125/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0125/RunCMakeTest.cmake36
-rw-r--r--Tests/RunCMake/CMP0126/CMP0126-NEW.cmake28
-rw-r--r--Tests/RunCMake/CMP0126/CMP0126-NEW_CL.cmake9
-rw-r--r--Tests/RunCMake/CMP0126/CMP0126-OLD.cmake25
-rw-r--r--Tests/RunCMake/CMP0126/CMP0126-OLD_CL.cmake9
-rw-r--r--Tests/RunCMake/CMP0126/CMP0126-WARN-default.cmake3
-rw-r--r--Tests/RunCMake/CMP0126/CMP0126-WARN-stderr.txt10
-rw-r--r--Tests/RunCMake/CMP0126/CMP0126-WARN.cmake5
-rw-r--r--Tests/RunCMake/CMP0126/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0126/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt1
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Parentheses.cmake7
-rw-r--r--Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/CMakeLists.txt84
-rw-r--r--Tests/RunCMake/CMakePresets/ConditionFuture-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ConditionFuture.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/Conditions.json.in406
-rw-r--r--Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/FuturePresetInstallDirField.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/FuturePresetToolchainField-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/FuturePresetToolchainField.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInstall.json.in30
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInstallCommandLine.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInstallDefault.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInstallInherit.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInstallOverride.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodToolchain.json.in30
-rw-r--r--Tests/RunCMake/CMakePresets/GoodToolchainCommandLine.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodToolchainDefault.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodToolchainInherit.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodToolchainOverride.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/HostSystemName.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/HostSystemName.json.in13
-rw-r--r--Tests/RunCMake/CMakePresets/HostSystemNameFuture-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/HostSystemNameFuture.json.in13
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidRegex-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidRegex.json.in15
-rw-r--r--Tests/RunCMake/CMakePresets/ListConditions-stdout.txt26
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresets-stdout.txt7
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresets.json.in5
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt7
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt7
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt7
-rw-r--r--Tests/RunCMake/CMakePresets/OptionalBinaryDirField.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/OptionalBinaryDirField.json.in9
-rw-r--r--Tests/RunCMake/CMakePresets/OptionalGeneratorField.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/OptionalGeneratorField.json.in9
-rw-r--r--Tests/RunCMake/CMakePresets/RunCMakeTest.cmake67
-rw-r--r--Tests/RunCMake/CMakePresets/SimpleFalse-result.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresets/SimpleFalse-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/SimpleTrue.cmake (renamed from Tests/RunCMake/TransformDepfile/empty.tlog.txt)0
-rw-r--r--Tests/RunCMake/CMakePresets/SubConditionNull-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/SubConditionNull.json.in14
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Condition.cmake (renamed from Tests/RunCMake/TransformDepfile/noexist.tlog.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Condition.json.in22
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/ConditionFuture.json.in17
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt3
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in12
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Condition.json.in22
-rw-r--r--Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/ConditionFuture.json.in17
-rw-r--r--Tests/RunCMake/CMakePresetsTest/ConditionListPresets-test-x-stdout.txt3
-rw-r--r--Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-result.txt)0
-rw-r--r--Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/ConditionRunTests.cmake2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/CPack/RPM/Prerequirements.cmake7
-rw-r--r--Tests/RunCMake/CPack/RPM/default_expected_stderr.txt3
-rw-r--r--Tests/RunCMake/CPack/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/CPack/VerifyResult.cmake38
-rw-r--r--Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/ExpectedFiles.cmake7
-rw-r--r--Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/test.cmake7
-rw-r--r--Tests/RunCMake/CPack/tests/DEBUGINFO/RPM-COMPONENT-stderr.txt17
-rw-r--r--Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake7
-rw-r--r--Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-no_scripts_single_debug_info-stderr.txt1
-rw-r--r--Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt1
-rw-r--r--Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake11
-rw-r--r--Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/VerifyResult.cmake39
-rw-r--r--Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake112
-rw-r--r--Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake2
-rw-r--r--Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake3
-rw-r--r--Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake37
-rw-r--r--Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake20
-rw-r--r--Tests/RunCMake/CPack/tests/SUGGESTS/test_suggests.spec22
-rw-r--r--Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake2
-rw-r--r--Tests/RunCMake/CPackSymlinks/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/CPackSymlinks/SrcSymlinksCheck.cmake21
-rw-r--r--Tests/RunCMake/CPackSymlinks/SrcSymlinksTar-stdout.txt7
-rw-r--r--Tests/RunCMake/CPackSymlinks/testcpacksym.tarbin10240 -> 20480 bytes
-rw-r--r--Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-stderr.txt3
-rw-r--r--Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/CTestCommandLine/output-junit-check.cmake36
-rw-r--r--Tests/RunCMake/CTestCommandLine/output-junit-result.txt1
-rw-r--r--Tests/RunCMake/CTestCommandLine/output-junit-stderr.txt1
-rw-r--r--Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt17
-rw-r--r--Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt17
-rw-r--r--Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt17
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake13
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake3
-rw-r--r--Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake27
-rw-r--r--Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake21
-rw-r--r--Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-large-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-space-bad-number-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build--parallel-zero-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-large-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-space-bad-number-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-jobs-zero-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/E_capabilities-stdout.txt2
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake2
-rw-r--r--Tests/RunCMake/CommandLine/E_create_symlink-broken-create-check.cmake2
-rw-r--r--Tests/RunCMake/CommandLine/E_create_symlink-broken-replace-check.cmake2
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchain.cmake3
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchainAbsolute-stdout.txt5
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchainAbsolute.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchainIgnore-stdout.txt4
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchainIgnore.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchainNone-stdout.txt3
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchainNone.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchainNoneExisting-stdout.txt4
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchainRelative-stdout.txt4
-rw-r--r--Tests/RunCMake/CommandLine/EnvToolchainRelative.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake62
-rw-r--r--Tests/RunCMake/CommandLine/Toolchain/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CommandLine/Toolchain/toolchain.cmake2
-rw-r--r--Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt3
-rw-r--r--Tests/RunCMake/CommandLine/build-no-dir-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt4
-rw-r--r--Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/install-prefix-no-arg-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/install-prefix-no-arg-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/toolchain-no-arg-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/toolchain-no-arg-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/toolchain-valid-abs-path-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/toolchain-valid-abs-path-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-result.txt)0
-rw-r--r--Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-stderr.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/C-launch-env-Build-stdout.txt (renamed from Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt)0
-rw-r--r--Tests/RunCMake/CompilerLauncher/CUDA-launch-env-Build-stdout.txt (renamed from Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt)0
-rw-r--r--Tests/RunCMake/CompilerLauncher/CXX-launch-env-Build-stdout.txt (renamed from Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt)0
-rw-r--r--Tests/RunCMake/CompilerLauncher/Fortran-launch-env-Build-stdout.txt (renamed from Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt)0
-rw-r--r--Tests/RunCMake/CompilerLauncher/HIP-common.cmake5
-rw-r--r--Tests/RunCMake/CompilerLauncher/HIP-env-Build-stdout.txt (renamed from Tests/RunCMake/CompilerLauncher/ISPC-env-launch-Build-stdout.txt)0
-rw-r--r--Tests/RunCMake/CompilerLauncher/HIP-env-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/HIP-env.cmake1
-rw-r--r--Tests/RunCMake/CompilerLauncher/HIP-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/HIP-launch-env.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/HIP-launch.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/HIP.cmake2
-rw-r--r--Tests/RunCMake/CompilerLauncher/ISPC-launch-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/CompilerLauncher/main.hip4
-rw-r--r--Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/ExternalProject/MultiCommand.cmake2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-check.py140
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json3
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json3
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json162
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json3
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json3
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json68
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json64
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json3
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json68
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json600
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json101
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json17
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json101
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2.cmake18
-rw-r--r--Tests/RunCMake/FileAPI/cxx/CMakeLists.txt17
-rw-r--r--Tests/RunCMake/FileAPI/imported/CMakeLists.txt7
-rw-r--r--Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/File_Generate/CustomFilePermissions.cmake1
-rw-r--r--Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake2
-rw-r--r--Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake2
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt4
-rw-r--r--Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake17
-rw-r--r--Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/FindPkgConfig/pc-empty/lib/pkgconfig/empty.pc5
-rw-r--r--Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt1
-rw-r--r--Tests/RunCMake/Framework/ImportedFrameworkTest.cmake10
-rw-r--r--Tests/RunCMake/Framework/RunCMakeTest.cmake12
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-stderr.txt10
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-stderr.txt10
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake18
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/TARGET_PROPERTY.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-TARGET_PROPERTY.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-result.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-stderr.txt10
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-stderr.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-stderr.txt10
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANGUAGE/unknown-lang.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-unknown-lang.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/RunCMakeTest.cmake18
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/TARGET_PROPERTY.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-TARGET_PROPERTY.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-stderr.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-stderr.txt (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/unknown-lang.cmake (renamed from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-unknown-lang.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake28
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-result.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_executable.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_library-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_library-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_library.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_test-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_test-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/add_test.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/install-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/install-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-stderr.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/install.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-stderr.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/link_depends.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-stderr.txt (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/target_sources.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-DEVICE_LINK/try_compile.cmake (renamed from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-try_compile.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake28
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_custom_command.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_custom_target.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_executable-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_executable-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_executable.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_library-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_library-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_library.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_test-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_test-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/add_test.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/install-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/install-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-stderr.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/install.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/link_depends-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/link_depends-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-stderr.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/link_depends.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_compile_options.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_include_directories.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_link_directories.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-result.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-result.txt)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_sources-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_sources-stderr.txt (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/target_sources.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-HOST_LINK/try_compile.cmake (renamed from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-try_compile.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-stderr.txt9
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-stderr.txt9
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-stderr.txt9
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/RunCMakeTest.cmake26
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-stderr.txt9
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-stderr.txt9
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/install-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/install-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-stderr.txt)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/install.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-stderr.txt9
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/unknown-lang.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-unknown-lang.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake24
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-stderr.txt)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/unknown-lang.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-unknown-lang.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-stderr.txt (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-stderr.txt)2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3.cmake (renamed from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3.cmake)0
-rw-r--r--Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake8
-rw-r--r--Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake8
-rw-r--r--Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX-imported-target.cmake2
-rw-r--r--Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX.cmake2
-rw-r--r--Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX-imported-target.cmake2
-rw-r--r--Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX.cmake2
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake15
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib1.c12
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib2.c6
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib3.c6
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/main.c4
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake37
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-stderr.txt9
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.c3
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.cmake9
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-stderr.txt5
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1.cmake4
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-result.txt1
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-stderr.txt5
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2.cmake6
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries.cmake5
-rw-r--r--Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp24
-rw-r--r--Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-stderr.txt11
-rw-r--r--Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir.cmake1
-rw-r--r--Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt2
-rw-r--r--Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake41
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnly-stderr.txt4
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-stderr.txt12
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout.cmake1
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake24
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir.cmake3
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake2
-rw-r--r--Tests/RunCMake/GeneratorToolset/VsNormal-stdout.txt2
-rw-r--r--Tests/RunCMake/GeneratorToolset/VsNormal.cmake6
-rw-r--r--Tests/RunCMake/GeneratorToolset/main.c4
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt6
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-property-timeout1-stdout.txt6
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-property-timeout2-stdout.txt6
-rw-r--r--Tests/RunCMake/GoogleTest/xml_output.cpp2
-rw-r--r--Tests/RunCMake/IfacePaths/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/LinkerLauncher/C-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/C-common.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/C-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/C-env.cmake1
-rw-r--r--Tests/RunCMake/LinkerLauncher/C-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/C-launch-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/C-launch-env.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/C-launch.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/C.cmake2
-rw-r--r--Tests/RunCMake/LinkerLauncher/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/LinkerLauncher/CXX-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/CXX-common.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/CXX-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/CXX-env.cmake1
-rw-r--r--Tests/RunCMake/LinkerLauncher/CXX-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/CXX-launch-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/CXX-launch-env.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/CXX-launch.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/CXX.cmake2
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJC-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJC-common.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJC-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJC-env.cmake1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJC-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJC-launch-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJC-launch-env.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJC-launch.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJC.cmake2
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJCXX-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJCXX-common.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJCXX-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJCXX-env.cmake1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJCXX-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJCXX-launch.cmake3
-rw-r--r--Tests/RunCMake/LinkerLauncher/OBJCXX.cmake2
-rw-r--r--Tests/RunCMake/LinkerLauncher/RunCMakeTest.cmake37
-rw-r--r--Tests/RunCMake/LinkerLauncher/main.c4
-rw-r--r--Tests/RunCMake/LinkerLauncher/main.cxx4
-rw-r--r--Tests/RunCMake/LinkerLauncher/main.m4
-rw-r--r--Tests/RunCMake/LinkerLauncher/main.mm4
-rw-r--r--Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake7
-rw-r--r--Tests/RunCMake/Ninja/CustomCommandDepfile.cmake13
-rw-r--r--Tests/RunCMake/Ninja/RunCMakeTest.cmake9
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake7
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile.cmake13
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt4
-rw-r--r--Tests/RunCMake/ParseImplicitData/linux-C-GNU-10.2.1-static-libgcc.input74
-rw-r--r--Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input79
-rw-r--r--Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input79
-rw-r--r--Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake3
-rw-r--r--Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-C-GNU-10.2.1-static-libgcc.output1
-rw-r--r--Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output1
-rw-r--r--Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake17
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/aix-CXX-XLClang-16.1.0.1.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-8.7.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-9.0-hlist-ad.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Intel-18.0.2.20180210.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-8.7.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-9.0-hlist-ad.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-GNU-7.3.0.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Intel-18.0.2.20180210.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-8.7.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-9.0-hlist-ad.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/darwin-CXX-AppleClang-8.0.0.8000042.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/darwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/freebsd-CXX-Clang-3.3.0.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-10.2.1-static-libgcc.output3
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output3
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-NVHPC-21.1.0.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output3
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/mingw.org-CXX-GNU-4.9.3.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd-CXX-GNU-4.8.5.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd_nostdinc-CXX-GNU-4.8.5.output2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/openbsd-CXX-Clang-5.0.1.output2
-rw-r--r--Tests/RunCMake/RunCMake.cmake102
-rw-r--r--Tests/RunCMake/RunCTest.cmake5
-rw-r--r--Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt4
-rw-r--r--Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake2
-rw-r--r--Tests/RunCMake/ToolchainFile/LangVars.cmake7
-rw-r--r--Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt6
-rw-r--r--Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt6
-rw-r--r--Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt1
-rw-r--r--Tests/RunCMake/TransformDepfile/vstlog.cmake16
-rw-r--r--Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt10
-rw-r--r--Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake10
-rw-r--r--Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake2
-rw-r--r--Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake10
-rw-r--r--Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake2
-rw-r--r--Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt10
-rw-r--r--Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake1
-rw-r--r--Tests/RunCMake/UseSWIG/CMP0122-common.cmake12
-rw-r--r--Tests/RunCMake/UseSWIG/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in18
-rw-r--r--Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake1
-rw-r--r--Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake8
-rw-r--r--Tests/RunCMake/WriteBasicConfigVersionFile/LeadingZeroes.cmake898
-rw-r--r--Tests/RunCMake/WriteBasicConfigVersionFile/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS-check.cmake4
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS.cmake1
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS-check.cmake4
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS.cmake1
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions.cmake21
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake16
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake16
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake16
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/Empty.txt0
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/Info.plist.in31
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake31
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake19
-rw-r--r--Tests/RunCMake/XcodeProject/InheritedParameters-check.cmake49
-rw-r--r--Tests/RunCMake/XcodeProject/InheritedParameters.cmake8
-rw-r--r--Tests/RunCMake/XcodeProject/RunCMakeTest.cmake27
-rw-r--r--Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake17
-rw-r--r--Tests/RunCMake/add_custom_command/RunCMakeTest.cmake17
-rw-r--r--Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake10
-rw-r--r--Tests/RunCMake/add_executable/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/add_library/RunCMakeTest.cmake14
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-component-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-component-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-component-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-component-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-component-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-component-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-component-stdout.txt3
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-stdout.txt3
-rw-r--r--Tests/RunCMake/build_command/ParallelLevel.cmake5
-rw-r--r--Tests/RunCMake/build_command/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt2
-rw-r--r--Tests/RunCMake/cmake_language/defer_call_ids.cmake2
-rw-r--r--Tests/RunCMake/configure_file/NoSourcePermissions.cmake2
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissions.cmake2
-rw-r--r--Tests/RunCMake/ctest_build/ParallelLevel-check.cmake11
-rw-r--r--Tests/RunCMake/ctest_build/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt9
-rw-r--r--Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt9
-rw-r--r--Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt9
-rw-r--r--Tests/RunCMake/ctest_test/OutputJUnit-check.cmake24
-rw-r--r--Tests/RunCMake/ctest_test/RunCMakeTest.cmake37
-rw-r--r--Tests/RunCMake/ctest_test/TestCompletionStatus-check.cmake16
-rw-r--r--Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt9
-rw-r--r--Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt9
-rw-r--r--Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt9
-rw-r--r--Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt9
-rw-r--r--Tests/RunCMake/ctest_test/TestMeasurements-check.cmake22
-rw-r--r--Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2.cmake2
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-all-check.cmake28
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter.cmake104
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake18
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt5
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-all-check.cmake18
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-rpath.cmake35
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-all-check.cmake18
-rw-r--r--Tests/RunCMake/file-RPATH/Common.cmake37
-rw-r--r--Tests/RunCMake/file/COPY_FILE-arg-missing-result.txt1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-arg-missing-stderr.txt3
-rw-r--r--Tests/RunCMake/file/COPY_FILE-arg-missing.cmake1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-arg-unknown-result.txt1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-arg-unknown-stderr.txt5
-rw-r--r--Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dir-to-file-capture-stdout.txt1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dir-to-file-capture.cmake8
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-result.txt1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-stderr.txt6
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake4
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture-stdout.txt1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture.cmake8
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-result.txt1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-stderr.txt6
-rw-r--r--Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake4
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-capture.cmake9
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-result.txt1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-stderr.txt6
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake5
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite.cmake12
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-replace.cmake9
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-to-dir-capture-stdout.txt1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-to-dir-capture.cmake9
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-result.txt1
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-stderr.txt6
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake5
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-to-file.cmake10
-rw-r--r--Tests/RunCMake/file/COPY_FILE-link-to-file.cmake10
-rw-r--r--Tests/RunCMake/file/REAL_PATH.cmake40
-rw-r--r--Tests/RunCMake/file/RENAME-arg-missing-result.txt1
-rw-r--r--Tests/RunCMake/file/RENAME-arg-missing-stderr.txt3
-rw-r--r--Tests/RunCMake/file/RENAME-arg-missing.cmake1
-rw-r--r--Tests/RunCMake/file/RENAME-arg-unknown-result.txt1
-rw-r--r--Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt5
-rw-r--r--Tests/RunCMake/file/RENAME-arg-unknown.cmake1
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt1
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake9
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt1
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt13
-rw-r--r--Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake5
-rw-r--r--Tests/RunCMake/file/RENAME-file-replace.cmake9
-rw-r--r--Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt1
-rw-r--r--Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake9
-rw-r--r--Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt1
-rw-r--r--Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt13
-rw-r--r--Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake5
-rw-r--r--Tests/RunCMake/file/RENAME-file-to-file.cmake10
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake39
-rw-r--r--Tests/RunCMake/find_file/FromPATHEnv-stdout-msys.txt9
-rw-r--r--Tests/RunCMake/find_file/NO_CACHE-stdout.txt18
-rw-r--r--Tests/RunCMake/find_file/NO_CACHE.cmake129
-rw-r--r--Tests/RunCMake/find_file/PrefixInPATH-stdout-msys.txt4
-rw-r--r--Tests/RunCMake/find_file/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/find_library/FromPATHEnv-stdout-msys.txt6
-rw-r--r--Tests/RunCMake/find_library/NO_CACHE-stdout.txt18
-rw-r--r--Tests/RunCMake/find_library/NO_CACHE.cmake133
-rw-r--r--Tests/RunCMake/find_library/PrefixInPATH-stdout-msys.txt4
-rw-r--r--Tests/RunCMake/find_library/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/find_package/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/find_package/VersionRangeCfg/VersionRangeCfgConfigVersion.cmake6
-rw-r--r--Tests/RunCMake/find_package/VersionRangeConfig02.cmake23
-rw-r--r--Tests/RunCMake/find_path/FromPATHEnv-stdout-msys.txt9
-rw-r--r--Tests/RunCMake/find_path/NO_CACHE-stdout.txt18
-rw-r--r--Tests/RunCMake/find_path/NO_CACHE.cmake131
-rw-r--r--Tests/RunCMake/find_path/PrefixInPATH-stdout-msys.txt4
-rw-r--r--Tests/RunCMake/find_path/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/find_program/NO_CACHE-stdout.txt18
-rw-r--r--Tests/RunCMake/find_program/NO_CACHE.cmake130
-rw-r--r--Tests/RunCMake/find_program/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/foreach/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake51
-rw-r--r--Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake53
-rw-r--r--Tests/RunCMake/get_property/directory_properties-stderr.txt4
-rw-r--r--Tests/RunCMake/get_property/directory_properties.cmake5
-rw-r--r--Tests/RunCMake/get_property/directory_properties/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/include_external_msproject/VSCSharpReference-check.cmake36
-rw-r--r--Tests/RunCMake/include_external_msproject/VSCSharpReference.cmake10
-rw-r--r--Tests/RunCMake/install/FILES-directory-result.txt1
-rw-r--r--Tests/RunCMake/install/FILES-directory-stderr.txt1
-rw-r--r--Tests/RunCMake/install/FILES-directory.cmake7
-rw-r--r--Tests/RunCMake/install/FILES-symlink-to-directory.cmake9
-rw-r--r--Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt1
-rw-r--r--Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt6
-rw-r--r--Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported.cmake2
-rw-r--r--Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-result.txt1
-rw-r--r--Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt5
-rw-r--r--Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported.cmake1
-rw-r--r--Tests/RunCMake/install/RunCMakeTest.cmake31
-rw-r--r--Tests/RunCMake/install/RuntimeDependencies-COMPONENTS.cmake39
-rw-r--r--Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake1
-rw-r--r--Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake1
-rw-r--r--Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake1
-rw-r--r--Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake5
-rw-r--r--Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake15
-rw-r--r--Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake17
-rw-r--r--Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake10
-rw-r--r--Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake8
-rw-r--r--Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake6
-rw-r--r--Tests/RunCMake/install/TARGETS-OUTPUT_NAME-all-check.cmake2
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-result.txt1
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-stderr.txt4
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross.cmake4
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty-all-check.cmake1
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty.cmake9
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-result.txt1
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-stderr.txt4
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework.cmake4
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-result.txt1
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-stderr.txt4
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle.cmake10
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep-all-check.cmake1
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep.cmake9
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-result.txt1
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-stderr.txt5
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported.cmake4
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-result.txt1
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-stderr.txt5
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict.cmake7
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt1
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt5
-rw-r--r--Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported.cmake4
-rw-r--r--Tests/RunCMake/option/CMP0077-OLD-stderr.txt10
-rw-r--r--Tests/RunCMake/project/ProjectIsTopLevel-stdout.txt2
-rw-r--r--Tests/RunCMake/project/ProjectIsTopLevel.cmake9
-rw-r--r--Tests/RunCMake/project/ProjectIsTopLevelMultiple-stdout.txt3
-rw-r--r--Tests/RunCMake/project/ProjectIsTopLevelMultiple.cmake14
-rw-r--r--Tests/RunCMake/project/ProjectIsTopLevelSubdirectory-stdout.txt6
-rw-r--r--Tests/RunCMake/project/ProjectIsTopLevelSubdirectory.cmake8
-rw-r--r--Tests/RunCMake/project/ProjectIsTopLevelSubdirectory/CMakeLists.txt5
-rw-r--r--Tests/RunCMake/project/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/target_compile_options/Order-build-stdout.txt3
-rw-r--r--Tests/RunCMake/target_compile_options/Order.cmake19
-rw-r--r--Tests/RunCMake/target_compile_options/RunCMakeTest.cmake13
-rw-r--r--Tests/RunCMake/target_compile_options/order.c7
-rw-r--r--Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stderr.txt10
-rw-r--r--Tests/RunCMake/target_link_libraries/CMP0079-link-OLD-stderr.txt13
-rw-r--r--Tests/SetLang/CMakeLists.txt4
-rw-r--r--Tests/StringFileTest/CMakeLists.txt2
-rw-r--r--Tests/SubDirSpaces/CMakeLists.txt2
-rw-r--r--Tests/TargetName/CMakeLists.txt2
-rw-r--r--Tests/TestDriver/CMakeLists.txt2
-rw-r--r--Tests/TestsWorkingDirectory/CMakeLists.txt2
-rw-r--r--Tests/TryCompile/CMakeLists.txt2
-rw-r--r--Tests/TryCompile/Inner/CMakeLists.txt2
-rw-r--r--Tests/UseSWIG/CMakeLists.txt3
-rw-r--r--Tests/VSExternalInclude/CMakeLists.txt6
-rw-r--r--Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt5
-rw-r--r--Utilities/Doxygen/CMakeLists.txt2
-rw-r--r--Utilities/IWYU/mapping.imp2
-rw-r--r--Utilities/Scripts/BoostScanDeps.cmake4
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rwxr-xr-xUtilities/Scripts/update-expat.bash2
-rwxr-xr-xUtilities/Scripts/update-liblzma.bash7
-rw-r--r--Utilities/Scripts/update-third-party.bash2
-rw-r--r--Utilities/Sphinx/CMakeLists.txt67
-rw-r--r--Utilities/Sphinx/cmake.py13
-rw-r--r--Utilities/cmThirdPartyChecks.cmake7
-rw-r--r--Utilities/cmbzip2/CMakeLists.txt2
-rw-r--r--Utilities/cmcurl/CMake/CurlTests.c20
-rw-r--r--Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake5
-rw-r--r--Utilities/cmcurl/CMakeLists.txt132
-rw-r--r--Utilities/cmcurl/include/curl/curl.h45
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h10
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h12
-rw-r--r--Utilities/cmcurl/lib/CMakeLists.txt17
-rw-r--r--Utilities/cmcurl/lib/Makefile.inc5
-rw-r--r--Utilities/cmcurl/lib/amigaos.c29
-rw-r--r--Utilities/cmcurl/lib/asyn-ares.c62
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c76
-rw-r--r--Utilities/cmcurl/lib/bufref.c127
-rw-r--r--Utilities/cmcurl/lib/bufref.h46
-rw-r--r--Utilities/cmcurl/lib/c-hyper.c47
-rw-r--r--Utilities/cmcurl/lib/conncache.c2
-rw-r--r--Utilities/cmcurl/lib/connect.c129
-rw-r--r--Utilities/cmcurl/lib/connect.h6
-rw-r--r--Utilities/cmcurl/lib/content_encoding.c9
-rw-r--r--Utilities/cmcurl/lib/cookie.c435
-rw-r--r--Utilities/cmcurl/lib/cookie.h13
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.c8
-rw-r--r--Utilities/cmcurl/lib/curl_config.h.cmake65
-rw-r--r--Utilities/cmcurl/lib/curl_endian.c6
-rw-r--r--Utilities/cmcurl/lib/curl_endian.h4
-rw-r--r--Utilities/cmcurl/lib/curl_get_line.c4
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.c2
-rw-r--r--Utilities/cmcurl/lib/curl_krb5.h1
-rw-r--r--Utilities/cmcurl/lib/curl_multibyte.c84
-rw-r--r--Utilities/cmcurl/lib/curl_multibyte.h43
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c145
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.h18
-rw-r--r--Utilities/cmcurl/lib/curl_path.c10
-rw-r--r--Utilities/cmcurl/lib/curl_rtmp.c8
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c302
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.h17
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h71
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h19
-rw-r--r--Utilities/cmcurl/lib/dict.c11
-rw-r--r--Utilities/cmcurl/lib/doh.c125
-rw-r--r--Utilities/cmcurl/lib/dynbuf.h4
-rw-r--r--Utilities/cmcurl/lib/easy.c58
-rw-r--r--Utilities/cmcurl/lib/easyoptions.c7
-rw-r--r--Utilities/cmcurl/lib/file.c40
-rw-r--r--Utilities/cmcurl/lib/ftp.c121
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.c3
-rw-r--r--Utilities/cmcurl/lib/getinfo.c10
-rw-r--r--Utilities/cmcurl/lib/gopher.c2
-rw-r--r--Utilities/cmcurl/lib/hash.c4
-rw-r--r--Utilities/cmcurl/lib/hostcheck.c8
-rw-r--r--Utilities/cmcurl/lib/hostip.c84
-rw-r--r--Utilities/cmcurl/lib/hostip.h10
-rw-r--r--Utilities/cmcurl/lib/hostip6.c19
-rw-r--r--Utilities/cmcurl/lib/hsts.c21
-rw-r--r--Utilities/cmcurl/lib/hsts.h8
-rw-r--r--Utilities/cmcurl/lib/http.c221
-rw-r--r--Utilities/cmcurl/lib/http.h16
-rw-r--r--Utilities/cmcurl/lib/http2.c219
-rw-r--r--Utilities/cmcurl/lib/http2.h6
-rw-r--r--Utilities/cmcurl/lib/http_aws_sigv4.c4
-rw-r--r--Utilities/cmcurl/lib/http_digest.c11
-rw-r--r--Utilities/cmcurl/lib/http_digest.h1
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.c2
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.c102
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c114
-rw-r--r--Utilities/cmcurl/lib/http_proxy.h24
-rw-r--r--Utilities/cmcurl/lib/imap.c10
-rw-r--r--Utilities/cmcurl/lib/inet_ntop.c4
-rw-r--r--Utilities/cmcurl/lib/krb5.c22
-rw-r--r--Utilities/cmcurl/lib/ldap.c40
-rw-r--r--Utilities/cmcurl/lib/llist.c6
-rw-r--r--Utilities/cmcurl/lib/md4.c33
-rw-r--r--Utilities/cmcurl/lib/md5.c31
-rw-r--r--Utilities/cmcurl/lib/memdebug.c35
-rw-r--r--Utilities/cmcurl/lib/mime.c4
-rw-r--r--Utilities/cmcurl/lib/mprintf.c4
-rw-r--r--Utilities/cmcurl/lib/mqtt.c1
-rw-r--r--Utilities/cmcurl/lib/multi.c480
-rw-r--r--Utilities/cmcurl/lib/multihandle.h50
-rw-r--r--Utilities/cmcurl/lib/non-ascii.c8
-rw-r--r--Utilities/cmcurl/lib/nonblock.c10
-rw-r--r--Utilities/cmcurl/lib/openldap.c138
-rw-r--r--Utilities/cmcurl/lib/pingpong.h7
-rw-r--r--Utilities/cmcurl/lib/pop3.c27
-rw-r--r--Utilities/cmcurl/lib/progress.c92
-rw-r--r--Utilities/cmcurl/lib/rtsp.c9
-rw-r--r--Utilities/cmcurl/lib/select.c2
-rw-r--r--Utilities/cmcurl/lib/sendf.c23
-rw-r--r--Utilities/cmcurl/lib/setopt.c170
-rw-r--r--Utilities/cmcurl/lib/setup-vms.h8
-rw-r--r--Utilities/cmcurl/lib/sha256.c42
-rw-r--r--Utilities/cmcurl/lib/share.c4
-rw-r--r--Utilities/cmcurl/lib/sigpipe.h4
-rw-r--r--Utilities/cmcurl/lib/smb.c11
-rw-r--r--Utilities/cmcurl/lib/smb.h6
-rw-r--r--Utilities/cmcurl/lib/smtp.c12
-rw-r--r--Utilities/cmcurl/lib/socketpair.h5
-rw-r--r--Utilities/cmcurl/lib/socks.c6
-rw-r--r--Utilities/cmcurl/lib/socks_gssapi.c2
-rw-r--r--Utilities/cmcurl/lib/socks_sspi.c2
-rw-r--r--Utilities/cmcurl/lib/splay.c18
-rw-r--r--Utilities/cmcurl/lib/strerror.c5
-rw-r--r--Utilities/cmcurl/lib/system_win32.c4
-rw-r--r--Utilities/cmcurl/lib/telnet.c3
-rw-r--r--Utilities/cmcurl/lib/tftp.c82
-rw-r--r--Utilities/cmcurl/lib/timeval.c8
-rw-r--r--Utilities/cmcurl/lib/transfer.c112
-rw-r--r--Utilities/cmcurl/lib/url.c387
-rw-r--r--Utilities/cmcurl/lib/urlapi.c96
-rw-r--r--Utilities/cmcurl/lib/urldata.h167
-rw-r--r--Utilities/cmcurl/lib/vauth/cleartext.c70
-rw-r--r--Utilities/cmcurl/lib/vauth/cram.c65
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.c62
-rw-r--r--Utilities/cmcurl/lib/vauth/digest_sspi.c54
-rw-r--r--Utilities/cmcurl/lib/vauth/gsasl.c124
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_gssapi.c100
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_sspi.c115
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c190
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm_sspi.c58
-rw-r--r--Utilities/cmcurl/lib/vauth/oauth2.c53
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.c25
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.h89
-rw-r--r--Utilities/cmcurl/lib/version.c59
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.c66
-rw-r--r--Utilities/cmcurl/lib/vquic/quiche.c33
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh.c157
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh2.c88
-rw-r--r--Utilities/cmcurl/lib/vssh/ssh.h3
-rw-r--r--Utilities/cmcurl/lib/vssh/wolfssh.c10
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.c28
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c40
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c139
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c53
-rw-r--r--Utilities/cmcurl/lib/vtls/mesalink.c22
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c65
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c583
-rw-r--r--Utilities/cmcurl/lib/vtls/rustls.c583
-rw-r--r--Utilities/cmcurl/lib/vtls/rustls.h33
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c138
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h3
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c285
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.c1759
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c73
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h39
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.c117
-rw-r--r--Utilities/cmcurl/lib/x509asn1.c6
-rw-r--r--Utilities/cmexpat/CMakeLists.txt4
-rw-r--r--Utilities/cmexpat/README.md89
-rw-r--r--Utilities/cmexpat/lib/ascii.h7
-rw-r--r--Utilities/cmexpat/lib/asciitab.h4
-rw-r--r--Utilities/cmexpat/lib/expat.h38
-rw-r--r--Utilities/cmexpat/lib/expat_external.h9
-rw-r--r--Utilities/cmexpat/lib/iasciitab.h4
-rw-r--r--Utilities/cmexpat/lib/internal.h58
-rw-r--r--Utilities/cmexpat/lib/latin1tab.h4
-rw-r--r--Utilities/cmexpat/lib/nametab.h4
-rw-r--r--Utilities/cmexpat/lib/siphash.h3
-rw-r--r--Utilities/cmexpat/lib/utf8tab.h4
-rw-r--r--Utilities/cmexpat/lib/winconfig.h19
-rw-r--r--Utilities/cmexpat/lib/xmlparse.c1222
-rw-r--r--Utilities/cmexpat/lib/xmlrole.c17
-rw-r--r--Utilities/cmexpat/lib/xmlrole.h5
-rw-r--r--Utilities/cmexpat/lib/xmltok.c42
-rw-r--r--Utilities/cmexpat/lib/xmltok.h6
-rw-r--r--Utilities/cmexpat/lib/xmltok_impl.c14
-rw-r--r--Utilities/cmexpat/lib/xmltok_impl.h3
-rw-r--r--Utilities/cmexpat/lib/xmltok_ns.c6
-rw-r--r--Utilities/cmjsoncpp/CMakeLists.txt2
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_reader.cpp2029
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_value.cpp1847
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_writer.cpp1420
-rw-r--r--Utilities/cmlibarchive/CMakeLists.txt2
-rw-r--r--Utilities/cmliblzma/CMakeLists.txt14
-rw-r--r--Utilities/cmliblzma/common/mythread.h521
-rw-r--r--Utilities/cmliblzma/common/sysdefs.h11
-rw-r--r--Utilities/cmliblzma/common/tuklib_common.h71
-rw-r--r--Utilities/cmliblzma/common/tuklib_config.h7
-rw-r--r--Utilities/cmliblzma/common/tuklib_cpucores.c100
-rw-r--r--Utilities/cmliblzma/common/tuklib_cpucores.h23
-rw-r--r--Utilities/cmliblzma/common/tuklib_integer.h506
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma.h5
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/block.h2
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/filter.h7
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/hardware.h2
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/lzma12.h2
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/version.h2
-rw-r--r--Utilities/cmliblzma/liblzma/api/lzma/vli.h2
-rw-r--r--Utilities/cmliblzma/liblzma/check/crc32_fast.c4
-rw-r--r--Utilities/cmliblzma/liblzma/check/crc32_table.c3
-rw-r--r--Utilities/cmliblzma/liblzma/check/crc64_fast.c4
-rw-r--r--Utilities/cmliblzma/liblzma/check/crc64_table.c3
-rw-r--r--Utilities/cmliblzma/liblzma/common/alone_decoder.c3
-rw-r--r--Utilities/cmliblzma/liblzma/common/alone_encoder.c9
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_header_decoder.c4
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_header_encoder.c2
-rw-r--r--Utilities/cmliblzma/liblzma/common/block_util.c2
-rw-r--r--Utilities/cmliblzma/liblzma/common/common.c8
-rw-r--r--Utilities/cmliblzma/liblzma/common/common.h1
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_common.h2
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_decoder.h2
-rw-r--r--Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c2
-rw-r--r--Utilities/cmliblzma/liblzma/common/hardware_physmem.c2
-rw-r--r--Utilities/cmliblzma/liblzma/common/index.c8
-rw-r--r--Utilities/cmliblzma/liblzma/common/memcmplen.h19
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_encoder_mt.c4
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c6
-rw-r--r--Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c8
-rw-r--r--Utilities/cmliblzma/liblzma/common/vli_decoder.c2
-rw-r--r--Utilities/cmliblzma/liblzma/delta/delta_decoder.c2
-rw-r--r--Utilities/cmliblzma/liblzma/lz/lz_decoder.c17
-rw-r--r--Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h2
-rw-r--r--Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c2
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/fastpos.h2
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/fastpos_tablegen.c1
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c8
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_common.h3
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c18
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c2
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c16
-rw-r--r--Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h3
-rw-r--r--Utilities/cmliblzma/liblzma/simple/arm.c6
-rw-r--r--Utilities/cmliblzma/liblzma/simple/armthumb.c8
-rw-r--r--Utilities/cmliblzma/liblzma/simple/ia64.c2
-rw-r--r--Utilities/cmliblzma/liblzma/simple/powerpc.c9
-rw-r--r--Utilities/cmliblzma/liblzma/simple/simple_coder.c10
-rw-r--r--Utilities/cmliblzma/liblzma/simple/simple_decoder.c2
-rw-r--r--Utilities/cmliblzma/liblzma/simple/simple_encoder.c2
-rw-r--r--Utilities/cmlibrhash/CMakeLists.txt2
-rw-r--r--Utilities/cmlibuv/CMakeLists.txt4
-rw-r--r--Utilities/cmnghttp2/CMakeLists.txt2
-rw-r--r--Utilities/cmzlib/CMakeLists.txt2
-rw-r--r--Utilities/cmzstd/CMakeLists.txt2
-rw-r--r--Utilities/std/cm/filesystem8
-rwxr-xr-xbootstrap38
1898 files changed, 39757 insertions, 15662 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 5e513fbd1..dda86b079 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -19,6 +19,7 @@ modernize-*,\
performance-*,\
readability-*,\
-readability-convert-member-functions-to-static,\
+-readability-function-cognitive-complexity,\
-readability-function-size,\
-readability-identifier-naming,\
-readability-implicit-bool-conversion,\
diff --git a/Auxiliary/vim/cmake.vim.in b/Auxiliary/vim/cmake.vim.in
index 3471b5455..6edc04073 100644
--- a/Auxiliary/vim/cmake.vim.in
+++ b/Auxiliary/vim/cmake.vim.in
@@ -9,7 +9,7 @@
" Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
" Last Change: @DATE@
"
-" Licence: The CMake license applies to this file. See
+" License: The CMake license applies to this file. See
" https://cmake.org/licensing
" This implies that distribution with Vim is allowed
diff --git a/Auxiliary/vim/indent/cmake.vim b/Auxiliary/vim/indent/cmake.vim
index 33e583d62..f7ab24a5d 100644
--- a/Auxiliary/vim/indent/cmake.vim
+++ b/Auxiliary/vim/indent/cmake.vim
@@ -5,7 +5,7 @@
" Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
" Last Change: 2017 Aug 30
"
-" Licence: The CMake license applies to this file. See
+" License: The CMake license applies to this file. See
" https://cmake.org/licensing
" This implies that distribution with Vim is allowed
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index 955beaea1..d2a04fec2 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -9,7 +9,7 @@
" Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
" Last Change: 2020 oct. 28
"
-" Licence: The CMake license applies to this file. See
+" License: The CMake license applies to this file. See
" https://cmake.org/licensing
" This implies that distribution with Vim is allowed
@@ -92,6 +92,7 @@ syn keyword cmakeProperty contained
\ AUTOUIC_EXECUTABLE
\ AUTOUIC_OPTIONS
\ AUTOUIC_SEARCH_PATHS
+ \ AUTOUIC_SOURCE_GROUP
\ BINARY_DIR
\ BUILDSYSTEM_TARGETS
\ BUILD_RPATH
@@ -904,6 +905,7 @@ syn keyword cmakeVariable contained
\ CMAKE_CXX_INCLUDE_WHAT_YOU_USE
\ CMAKE_CXX_INIT
\ CMAKE_CXX_LIBRARY_ARCHITECTURE
+ \ CMAKE_CXX_LINKER_LAUNCHER
\ CMAKE_CXX_LINKER_PREFERENCE
\ CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES
\ CMAKE_CXX_LINKER_WRAPPER_FLAG
@@ -969,6 +971,7 @@ syn keyword cmakeVariable contained
\ CMAKE_C_INCLUDE_WHAT_YOU_USE
\ CMAKE_C_INIT
\ CMAKE_C_LIBRARY_ARCHITECTURE
+ \ CMAKE_C_LINKER_LAUNCHER
\ CMAKE_C_LINKER_PREFERENCE
\ CMAKE_C_LINKER_PREFERENCE_PROPAGATES
\ CMAKE_C_LINKER_WRAPPER_FLAG
@@ -1262,10 +1265,12 @@ syn keyword cmakeVariable contained
\ CMAKE_NO_SYSTEM_FROM_IMPORTED
\ CMAKE_OBJCXX_CLANG_TIDY
\ CMAKE_OBJCXX_EXTENSIONS
+ \ CMAKE_OBJCXX_LINKER_LAUNCHER
\ CMAKE_OBJCXX_STANDARD
\ CMAKE_OBJCXX_STANDARD_REQUIRED
\ CMAKE_OBJC_CLANG_TIDY
\ CMAKE_OBJC_EXTENSIONS
+ \ CMAKE_OBJC_LINKER_LAUNCHER
\ CMAKE_OBJC_STANDARD
\ CMAKE_OBJC_STANDARD_REQUIRED
\ CMAKE_OBJECT_PATH_MAX
diff --git a/CMakeCPack.cmake b/CMakeCPack.cmake
index 31c2fe456..935780463 100644
--- a/CMakeCPack.cmake
+++ b/CMakeCPack.cmake
@@ -133,6 +133,9 @@ if(CMake_INSTALL_COMPONENTS)
if(SPHINX_QTHELP)
list(APPEND _CPACK_IFW_COMPONENTS_ALL sphinx-qthelp)
endif()
+ if(SPHINX_LATEXPDF)
+ list(APPEND _CPACK_IFW_COMPONENTS_ALL sphinx-latexpdf)
+ endif()
if(CMake_BUILD_DEVELOPER_REFERENCE)
if(CMake_BUILD_DEVELOPER_REFERENCE_HTML)
list(APPEND _CPACK_IFW_COMPONENTS_ALL cmake-developer-reference-html)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a2fcf2e37..44b433ac8 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.1...3.18 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.1...3.19 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)
project(CMake)
@@ -579,6 +579,7 @@ macro (CMAKE_BUILD_UTILITIES)
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()
@@ -643,7 +644,11 @@ macro (CMAKE_BUILD_UTILITIES)
#---------------------------------------------------------------------
# Build libuv library.
if(CMAKE_USE_SYSTEM_LIBUV)
- find_package(LibUV 1.10.0)
+ if(WIN32)
+ find_package(LibUV 1.38.0)
+ else()
+ find_package(LibUV 1.10.0)
+ endif()
if(NOT LIBUV_FOUND)
message(FATAL_ERROR
"CMAKE_USE_SYSTEM_LIBUV is ON but a libuv is not found!")
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 300621405..a6a20827d 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -38,7 +38,7 @@ To contribute patches:
#. Push the topic branch to a personal repository fork on GitLab.
#. Create a GitLab Merge Request targeting the upstream ``master`` branch
(even if the change is intended for merge to the ``release`` branch).
- Check the box labelled "Allow commits from members who can merge to the
+ Check the box labeled "Allow commits from members who can merge to the
target branch". This will allow maintainers to make minor edits on your
behalf.
diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in
index 4c8267de8..093c1d889 100644
--- a/CTestCustom.cmake.in
+++ b/CTestCustom.cmake.in
@@ -7,6 +7,7 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION
"warning LNK4221"
"warning LNK4204" # Occurs by race condition with objects in small libs
"variable .var_args[2]*. is used before its value is set"
+ "warning: variable .__d[01]. was set but never used" # FD_ZERO on NVHPC
"jobserver unavailable"
"warning: \\(Long double usage is reported only once for each file"
"warning: To disable this warning use"
@@ -82,28 +83,21 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION
"compilation completed with warnings" # PGI
"[0-9]+ Warning\\(s\\) detected" # SunPro
- # scanbuild exceptions
- "char_traits.h:.*: warning: Null pointer argument in call to string length function"
- "stl_construct.h:.*: warning: Forming reference to null pointer"
- ".*stl_uninitialized.h:75:19: warning: Forming reference to null pointer.*"
- ".*stl_vector.h:.*: warning: Returning null reference.*"
- "warning: Value stored to 'yymsg' is never read"
- "warning: Value stored to 'yytoken' is never read"
- "index_encoder.c.241.2. warning: Value stored to .out_start. is never read"
- "index.c.*warning: Access to field.*results in a dereference of a null pointer.*loaded from variable.*"
- "cmCommandArgumentLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes"
- "cmDependsJavaLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes"
- "cmExprLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes"
- "cmListFileLexer.c:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes"
- "cmFortranLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes"
- "testProcess.*warning: Dereference of null pointer .loaded from variable .invalidAddress.."
+ # 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"
+ "liblzma/common/index_encoder.c:[0-9]+:[0-9]+: warning: Value stored to '[^']+' during its initialization is never read"
+ "liblzma/liblzma/common/index.c:[0-9]+:[0-9]+: warning: Access to field '[^']+' results in a dereference of a null pointer"
"liblzma/simple/x86.c:[0-9]+:[0-9]+: warning: The result of the '<<' expression is undefined"
- "liblzma/common/index_encoder.c:[0-9]+:[0-9]+: warning: Value stored to .* during its initialization is never read"
- "libuv/src/.*:[0-9]+:[0-9]+: warning: Dereference of null pointer"
- "libuv/src/.*:[0-9]+:[0-9]+: warning: The left operand of '==' is a garbage value"
+ "librhash/librhash/.*:[0-9]+:[0-9]+: warning: The left operand of '[^']+' is a garbage value"
"libuv/src/.*:[0-9]+:[0-9]+: warning: 1st function call argument is an uninitialized value"
+ "libuv/src/.*:[0-9]+:[0-9]+: warning: Dereference of null pointer"
+ "libuv/src/.*:[0-9]+:[0-9]+: warning: The left operand of '[^']+' is a garbage value"
+ "nghttp2/lib/.*:[0-9]+:[0-9]+: warning: Access to field '[^']+' results in a dereference of a null pointer"
"nghttp2/lib/.*:[0-9]+:[0-9]+: warning: Dereference of null pointer"
- "nghttp2/lib/.*:[0-9]+:[0-9]+: warning: Value stored to .* is never read"
+ "nghttp2/lib/.*:[0-9]+:[0-9]+: warning: Value stored to '[^']+' is never read"
+ "zstd/lib/.*:[0-9]+:[0-9]+: warning: Assigned value is garbage or undefined"
+ "zstd/lib/.*:[0-9]+:[0-9]+: warning: Dereference of null pointer"
)
if(NOT "@CMAKE_GENERATOR@" MATCHES "Xcode")
diff --git a/Help/command/DEVICE_LINK_OPTIONS.txt b/Help/command/DEVICE_LINK_OPTIONS.txt
index 1297cd054..3d5020816 100644
--- a/Help/command/DEVICE_LINK_OPTIONS.txt
+++ b/Help/command/DEVICE_LINK_OPTIONS.txt
@@ -1,3 +1,5 @@
+Host And Device Specific Link Options
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. versionadded:: 3.18
When a device link step is involved, which is controlled by
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index 97eecfca3..5b63e1cba 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -11,10 +11,11 @@ The general signature is:
|FIND_XXX| (
<VAR>
name | |NAMES|
- [HINTS path1 [path2 ... ENV var]]
- [PATHS path1 [path2 ... ENV var]]
+ [HINTS [path | ENV var]... ]
+ [PATHS [path | ENV var]... ]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[DOC "cache documentation string"]
+ [NO_CACHE]
[REQUIRED]
[NO_DEFAULT_PATH]
[NO_PACKAGE_ROOT_PATH]
@@ -28,8 +29,8 @@ The general signature is:
)
This command is used to find a |SEARCH_XXX_DESC|.
-A cache entry named by ``<VAR>`` is created to store the result
-of this command.
+A cache entry, or a normal variable if ``NO_CACHE`` is specified,
+named by ``<VAR>`` is created to store the result of this command.
If the |SEARCH_XXX| is found the result is stored in the variable
and the search will not be repeated unless the variable is cleared.
If nothing is found, the result will be ``<VAR>-NOTFOUND``.
@@ -56,6 +57,22 @@ Options include:
``DOC``
Specify the documentation string for the ``<VAR>`` cache entry.
+``NO_CACHE``
+ .. versionadded:: 3.21
+
+ The result of the search will be stored in a normal variable rather than
+ a cache entry.
+
+ .. note::
+
+ If the variable is already set before the call (as a normal or cache
+ variable) then the search will not occur.
+
+ .. warning::
+
+ This option should be used with caution because it can greatly increase
+ the cost of repeated configure steps.
+
``REQUIRED``
.. versionadded:: 3.18
diff --git a/Help/command/LINK_OPTIONS_LINKER.txt b/Help/command/LINK_OPTIONS_LINKER.txt
index 3f66181be..e71e5ea25 100644
--- a/Help/command/LINK_OPTIONS_LINKER.txt
+++ b/Help/command/LINK_OPTIONS_LINKER.txt
@@ -1,3 +1,6 @@
+Handling Compiler Driver Differences
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
To pass options to the linker tool, each compiler driver has its own syntax.
The ``LINKER:`` prefix and ``,`` separator can be used to specify, in a portable
way, options to pass to the linker tool. ``LINKER:`` is replaced by the
diff --git a/Help/command/OPTIONS_SHELL.txt b/Help/command/OPTIONS_SHELL.txt
index 4051ffe16..4171f0162 100644
--- a/Help/command/OPTIONS_SHELL.txt
+++ b/Help/command/OPTIONS_SHELL.txt
@@ -1,11 +1,15 @@
-The final set of compile or link options used for a target is constructed by
+Option De-duplication
+^^^^^^^^^^^^^^^^^^^^^
+
+The final set of options used for a target is constructed by
accumulating options from the current target and the usage requirements of
its dependencies. The set of options is de-duplicated to avoid repetition.
.. versionadded:: 3.12
While beneficial for individual options, the de-duplication step can break
- up option groups. For example, ``-D A -D B`` becomes ``-D A B``. One may
- specify a group of options using shell-like quoting along with a ``SHELL:``
- prefix. The ``SHELL:`` prefix is dropped, and the rest of the option string
- is parsed using the :command:`separate_arguments` ``UNIX_COMMAND`` mode.
- For example, ``"SHELL:-D A" "SHELL:-D B"`` becomes ``-D A -D B``.
+ up option groups. For example, ``-option A -option B`` becomes
+ ``-option A B``. One may specify a group of options using shell-like
+ quoting along with a ``SHELL:`` prefix. The ``SHELL:`` prefix is dropped,
+ and the rest of the option string is parsed using the
+ :command:`separate_arguments` ``UNIX_COMMAND`` mode. For example,
+ ``"SHELL:-option A" "SHELL:-option B"`` becomes ``-option A -option B``.
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index c0b95934b..d881a66b5 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -271,21 +271,30 @@ The options are:
``DEPFILE``
.. versionadded:: 3.7
- Specify a ``.d`` depfile for the :generator:`Ninja` generator and
- :ref:`Makefile Generators`.
- A ``.d`` file holds dependencies usually emitted by the custom
- command itself.
- Using ``DEPFILE`` with other generators than :generator:`Ninja` or
- :ref:`Makefile Generators` is an error.
+ Specify a ``.d`` depfile for the :generator:`Ninja`, :generator:`Xcode` and
+ :ref:`Makefile <Makefile Generators>` generators. The depfile may use
+ "generator expressions" with the syntax ``$<...>``. See the
+ :manual:`generator-expressions(7) <cmake-generator-expressions(7)>` manual
+ for available expressions. A ``.d`` file holds dependencies usually emitted
+ by the custom command itself.
+
+ Using ``DEPFILE`` with other generators than :generator:`Ninja`,
+ :generator:`Xcode` or :ref:`Makefile <Makefile Generators>` is an error.
.. versionadded:: 3.20
- Added the support of :ref:`Makefile Generators`.
+ Added support for :ref:`Makefile Generators`.
+
+ .. versionadded:: 3.21
+ Added support for :ref:`Visual Studio Generators` with VS 2012 and above,
+ for the :generator:`Xcode` generator, and for
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
If the ``DEPFILE`` argument is relative, it should be relative to
:variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the
``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`
(see policy :policy:`CMP0116`. This policy is always ``NEW`` for
- :ref:`Makefile Generators`).
+ :ref:`Makefile Generators`, :ref:`Visual Studio Generators`,
+ and the :generator:`Xcode` generator).
.. note::
@@ -331,6 +340,8 @@ will re-run whenever ``in.txt`` changes.
where ``<config>`` is the build configuration, and then compile the generated
source as part of a library.
+.. _`add_custom_command(TARGET)`:
+
Build Events
^^^^^^^^^^^^
@@ -381,6 +392,9 @@ of the following is specified:
This allows to add individual build events for every configuration.
+.. versionadded:: 3.21
+ Support for target-dependent generator expressions.
+
Examples: Build Events
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Help/command/build_command.rst b/Help/command/build_command.rst
index 6659005be..a03979d10 100644
--- a/Help/command/build_command.rst
+++ b/Help/command/build_command.rst
@@ -8,23 +8,29 @@ This is mainly intended for internal use by the :module:`CTest` module.
build_command(<variable>
[CONFIGURATION <config>]
+ [PARALLEL_LEVEL <parallel>]
[TARGET <target>]
[PROJECT_NAME <projname>] # legacy, causes warning
)
Sets the given ``<variable>`` to a command-line string of the form::
- <cmake> --build . [--config <config>] [--target <target>...] [-- -i]
+ <cmake> --build . [--config <config>] [--parallel <parallel>] [--target <target>...] [-- -i]
where ``<cmake>`` is the location of the :manual:`cmake(1)` command-line
-tool, and ``<config>`` and ``<target>`` are the values provided to the
-``CONFIGURATION`` and ``TARGET`` options, if any. The trailing ``-- -i``
-option is added for :ref:`Makefile Generators` if policy :policy:`CMP0061`
-is not set to ``NEW``.
+tool, and ``<config>``, ``<parallel>`` and ``<target>`` are the values
+provided to the ``CONFIGURATION``, ``PARALLEL_LEVEL`` and ``TARGET``
+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
underlying build system tool.
+.. versionadded:: 3.21
+ The ``PARALLEL_LEVEL`` argument can be used to set the ``--parallel``
+ flag.
+
.. code-block:: cmake
build_command(<cachevariable> <makecommand>)
diff --git a/Help/command/cmake_language.rst b/Help/command/cmake_language.rst
index 99f874b19..2859f6b6d 100644
--- a/Help/command/cmake_language.rst
+++ b/Help/command/cmake_language.rst
@@ -190,7 +190,7 @@ For example, the code:
.. code-block:: cmake
cmake_language(DEFER CALL message "${deferred_message}")
- cmake_language(DEFER ID_VAR id CALL message "Cancelled Message")
+ cmake_language(DEFER ID_VAR id CALL message "Canceled Message")
cmake_language(DEFER CANCEL_CALL ${id})
message("Immediate Message")
set(deferred_message "Deferred Message")
@@ -201,7 +201,7 @@ prints::
Deferred Message
The ``Cancelled Message`` is never printed because its command is
-cancelled. The ``deferred_message`` variable reference is not evaluated
+canceled. The ``deferred_message`` variable reference is not evaluated
until the call site, so it can be set after the deferred call is scheduled.
In order to evaluate variable references immediately when scheduling a
diff --git a/Help/command/cmake_minimum_required.rst b/Help/command/cmake_minimum_required.rst
index c3b3e7370..d15977049 100644
--- a/Help/command/cmake_minimum_required.rst
+++ b/Help/command/cmake_minimum_required.rst
@@ -5,21 +5,21 @@ Require a minimum version of cmake.
.. code-block:: cmake
- cmake_minimum_required(VERSION <min>[...<max>] [FATAL_ERROR])
+ cmake_minimum_required(VERSION <min>[...<policy_max>] [FATAL_ERROR])
.. versionadded:: 3.12
- The optional ``<max>`` version.
+ The optional ``<policy_max>`` version.
Sets the minimum required version of cmake for a project.
Also updates the policy settings as explained below.
-``<min>`` and the optional ``<max>`` are each CMake versions of the form
-``major.minor[.patch[.tweak]]``, and the ``...`` is literal.
+``<min>`` and the optional ``<policy_max>`` are each CMake versions of the
+form ``major.minor[.patch[.tweak]]``, and the ``...`` is literal.
If the running version of CMake is lower than the ``<min>`` required
version it will stop processing the project and report an error.
-The optional ``<max>`` version, if specified, must be at least the
-``<min>`` version and affects policy settings as described below.
+The optional ``<policy_max>`` version, if specified, must be at least the
+``<min>`` version and affects policy settings as described in `Policy Settings`_.
If the running version of CMake is older than 3.12, the extra ``...``
dots will be seen as version component separators, resulting in the
``...<max>`` part being ignored and preserving the pre-3.12 behavior
@@ -40,8 +40,15 @@ with an error instead of just a warning.
they may affect. See also policy :policy:`CMP0000`.
Calling ``cmake_minimum_required()`` inside a :command:`function`
- limits some effects to the function scope when invoked. Such calls
- should not be made with the intention of having global effects.
+ limits some effects to the function scope when invoked. For example,
+ the :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable won't be set
+ in the calling scope. Functions do not introduce their own policy
+ scope though, so policy settings of the caller *will* be affected
+ (see below). Due to this mix of things that do and do not affect the
+ calling scope, calling ``cmake_minimum_required()`` inside a function
+ is generally discouraged.
+
+.. _`Policy Settings`:
Policy Settings
^^^^^^^^^^^^^^^
diff --git a/Help/command/cmake_path.rst b/Help/command/cmake_path.rst
index e7a01ab60..565a37b6a 100644
--- a/Help/command/cmake_path.rst
+++ b/Help/command/cmake_path.rst
@@ -688,7 +688,8 @@ When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
<Normalization>` after the path computation.
Because ``cmake_path()`` does not access the filesystem, symbolic links are
-not resolved. To compute a real path with symbolic links resolved, use the
+not resolved and any leading tilde is not expanded. To compute a real path
+with symbolic links resolved and leading tildes expanded, use the
:command:`file(REAL_PATH)` command instead.
Native Conversion
diff --git a/Help/command/configure_file.rst b/Help/command/configure_file.rst
index d00f08b7a..086668c16 100644
--- a/Help/command/configure_file.rst
+++ b/Help/command/configure_file.rst
@@ -36,8 +36,30 @@ or
depending on whether ``VAR`` is set in CMake to any value not considered
a false constant by the :command:`if` command. The "..." content on the
line after the variable name, if any, is processed as above.
-Input file lines of the form ``#cmakedefine01 VAR`` will be replaced with
-either ``#define VAR 1`` or ``#define VAR 0`` similarly.
+
+Unlike lines of the form ``#cmakedefine VAR ...``, in lines of the form
+``#cmakedefine01 VAR``, ``VAR`` itself will expand to ``VAR 0`` or ``VAR 1``
+rather than being assigned the value ``...``. Therefore, input lines of the form
+
+.. code-block:: c
+
+ #cmakedefine01 VAR
+
+will be replaced with either
+
+.. code-block:: c
+
+ #define VAR 0
+
+or
+
+.. code-block:: c
+
+ #define VAR 1
+
+Input lines of the form ``#cmakedefine01 VAR ...`` will expand
+as ``#cmakedefine01 VAR ... 0`` or ``#cmakedefine01 VAR ... 0``,
+which may lead to undefined behavior.
.. versionadded:: 3.10
The result lines (with the exception of the ``#undef`` comments) can be
diff --git a/Help/command/ctest_build.rst b/Help/command/ctest_build.rst
index 4d6dc5a43..e05df1afc 100644
--- a/Help/command/ctest_build.rst
+++ b/Help/command/ctest_build.rst
@@ -7,6 +7,7 @@ Perform the :ref:`CTest Build Step` as a :ref:`Dashboard Client`.
ctest_build([BUILD <build-dir>] [APPEND]
[CONFIGURATION <config>]
+ [PARALLEL_LEVEL <parallel>]
[FLAGS <flags>]
[PROJECT_NAME <project-name>]
[TARGET <target-name>]
@@ -42,6 +43,13 @@ The options are:
Otherwise the ``-C <cfg>`` option given to the :manual:`ctest(1)`
command will be used, if any.
+``PARALLEL_LEVEL <parallel>``
+ .. versionadded:: 3.21
+
+ Specify the parallel level of the underlying build system. If not
+ specified, the :envvar:`CMAKE_BUILD_PARALLEL_LEVEL` environment
+ variable will be checked.
+
``FLAGS <flags>``
Pass additional arguments to the underlying build command.
If not specified the ``CTEST_BUILD_FLAGS`` variable will be checked.
diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst
index b4493a03d..2153c90de 100644
--- a/Help/command/ctest_test.rst
+++ b/Help/command/ctest_test.rst
@@ -25,6 +25,7 @@ Perform the :ref:`CTest Test Step` as a :ref:`Dashboard Client`.
[RETURN_VALUE <result-var>]
[CAPTURE_CMAKE_ERROR <result-var>]
[REPEAT <mode>:<n>]
+ [OUTPUT_JUNIT <file>]
[QUIET]
)
@@ -150,6 +151,15 @@ The options are:
Store in the ``<result-var>`` variable -1 if there are any errors running
the command and prevent ctest from returning non-zero if an error occurs.
+``OUTPUT_JUNIT``
+ .. versionadded:: 3.21
+
+ Write test results to ``<file>`` in JUnit XML format. If ``<file>`` is a
+ relative path it will be placed in the build directory. If ``<file>>``
+ already exists it will be overwritten. Note that the resulting JUnit XML
+ file is **not** uploaded to CDash because it would be redundant with
+ CTest's ``Test.xml`` file.
+
``QUIET``
.. versionadded:: 3.3
@@ -160,3 +170,103 @@ The options are:
See also the :variable:`CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE`
and :variable:`CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE` variables.
+
+.. _`Additional Test Measurements`:
+
+Additional Test Measurements
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+CTest can parse the output of your tests for extra measurements to report
+to CDash.
+
+When run as a :ref:`Dashboard Client`, CTest will include these custom
+measurements in the ``Test.xml`` file that gets uploaded to CDash.
+
+Check the `CDash test measurement documentation
+<https://github.com/Kitware/CDash/blob/master/docs/test_measurements.md>`_
+for more information on the types of test measurements that CDash recognizes.
+
+The following example demonstrates how to output a variety of custom test
+measurements.
+
+.. code-block:: c++
+
+ std::cout <<
+ "<DartMeasurement type=\"numeric/double\" name=\"score\">28.3</DartMeasurement>"
+ << std::endl;
+
+ std::cout <<
+ "<DartMeasurement type=\"text/string\" name=\"color\">red</DartMeasurement>"
+ << std::endl;
+
+ std::cout <<
+ "<DartMeasurement type=\"text/link\" name=\"CMake URL\">https://cmake.org</DartMeasurement>"
+ << std::endl;
+
+ std::cout <<
+ "<DartMeasurement type=\"text/preformatted\" name=\"Console Output\">" <<
+ "line 1.\n" <<
+ " \033[31;1m line 2. Bold red, and indented!\033[0;0ml\n" <<
+ "line 3. Not bold or indented...\n" <<
+ "</DartMeasurement>" << std::endl;
+
+Image Measurements
+""""""""""""""""""
+
+The following example demonstrates how to upload test images to CDash.
+
+.. code-block:: c++
+
+ std::cout <<
+ "<DartMeasurementFile type=\"image/jpg\" name=\"TestImage\">" <<
+ "/dir/to/test_img.jpg</DartMeasurementFile>" << std::endl;
+
+ std::cout <<
+ "<DartMeasurementFile type=\"image/gif\" name=\"ValidImage\">" <<
+ "/dir/to/valid_img.gif</DartMeasurementFile>" << std::endl;
+
+ std::cout <<
+ "<DartMeasurementFile type=\"image/png\" name=\"AlgoResult\"> <<
+ "/dir/to/img.png</DartMeasurementFile>"
+ << std::endl;
+
+Images will be displayed together in an interactive comparison mode on CDash
+if they are provided with two or more of the following names.
+
+* ``TestImage``
+* ``ValidImage``
+* ``BaselineImage``
+* ``DifferenceImage2``
+
+By convention, ``TestImage`` is the image generated by your test, and
+``ValidImage`` (or ``BaselineImage``) is basis of comparison used to determine
+if the test passed or failed.
+
+If another image name is used it will be displayed by CDash as a static image
+separate from the interactive comparison UI.
+
+Attached Files
+""""""""""""""
+
+The following example demonstrates how to upload non-image files to CDash.
+
+.. code-block:: c++
+
+ std::cout <<
+ "<DartMeasurementFile type=\"file\" name=\"MyTestInputData\">" <<
+ "/dir/to/data.csv</DartMeasurementFile>" << std::endl;
+
+If the name of the file to upload is known at configure time, you can use the
+:prop_test:`ATTACHED_FILES` or :prop_test:`ATTACHED_FILES_ON_FAIL` test
+properties instead.
+
+Custom Details
+""""""""""""""
+
+The following example demonstrates how to specify a custom value for the
+``Test Details`` field displayed on CDash.
+
+.. code-block:: c++
+
+ std::cout <<
+ "<CTestDetails>My Custom Details Value</CTestDetails>" << std::endl;
diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst
index ce765de68..d2acbc85c 100644
--- a/Help/command/enable_language.rst
+++ b/Help/command/enable_language.rst
@@ -10,7 +10,7 @@ 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
variables that are created by the project command. Example languages
are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``,
-``ISPC``, and ``ASM``.
+``HIP``, ``ISPC``, and ``ASM``.
.. versionadded:: 3.8
Added ``CUDA`` support.
@@ -21,6 +21,9 @@ are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``,
.. versionadded:: 3.18
Added ``ISPC`` support.
+.. versionadded:: 3.21
+ Added ``HIP`` support.
+
If enabling ``ASM``, enable it last so that CMake can check whether
compilers for other languages like ``C`` work for assembly too.
diff --git a/Help/command/file.rst b/Help/command/file.rst
index 31de610b2..943bf7c1b 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -38,7 +38,8 @@ Synopsis
`Filesystem`_
file({`GLOB`_ | `GLOB_RECURSE`_} <out-var> [...] [<globbing-expr>...])
- file(`RENAME`_ <oldname> <newname>)
+ file(`RENAME`_ <oldname> <newname> [...])
+ file(`COPY_FILE`_ <oldname> <newname> [...])
file({`REMOVE`_ | `REMOVE_RECURSE`_ } [<files>...])
file(`MAKE_DIRECTORY`_ [<dir>...])
file({`COPY`_ | `INSTALL`_} <file>... DESTINATION <dir> [...])
@@ -49,7 +50,7 @@ Synopsis
file(`CHMOD_RECURSE`_ <files>... <directories>... PERMISSIONS <permissions>... [...])
`Path Conversion`_
- file(`REAL_PATH`_ <path> <out-var> [BASE_DIRECTORY <dir>])
+ file(`REAL_PATH`_ <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE])
file(`RELATIVE_PATH`_ <out-var> <directory> <file>)
file({`TO_CMAKE_PATH`_ | `TO_NATIVE_PATH`_} <path> <out-var>)
@@ -115,7 +116,8 @@ Parse a list of ASCII strings from ``<filename>`` and store it in
binary while reading unless this option is given.
``REGEX <regex>``
- Consider only strings that match the given regular expression.
+ Consider only strings that match the given regular expression,
+ as described under :ref:`string(REGEX) <Regex Specification>`.
``ENCODING <encoding-type>``
.. versionadded:: 3.1
@@ -178,6 +180,8 @@ the ``<format>`` and ``UTC`` options.
[PRE_EXCLUDE_REGEXES [<regexes>...]]
[POST_INCLUDE_REGEXES [<regexes>...]]
[POST_EXCLUDE_REGEXES [<regexes>...]]
+ [POST_INCLUDE_FILES [<files>...]]
+ [POST_EXCLUDE_FILES [<files>...]]
)
.. versionadded:: 3.16
@@ -185,8 +189,10 @@ the ``<format>`` and ``UTC`` options.
Recursively get the list of libraries depended on by the given files.
Please note that this sub-command is not intended to be used in project mode.
-Instead, use it in an :command:`install(CODE)` or :command:`install(SCRIPT)`
-block. For example:
+It is intended for use at install time, either from code generated by the
+:command:`install(RUNTIME_DEPENDENCY_SET)` command, or from code provided by
+the project via :command:`install(CODE)` or :command:`install(SCRIPT)`.
+For example:
.. code-block:: cmake
@@ -275,6 +281,18 @@ be resolved. See below for a full description of how they work.
List of post-exclude regexes through which to filter the names of resolved
dependencies.
+``POST_INCLUDE_FILES <files>``
+ .. versionadded:: 3.21
+
+ List of post-include filenames through which to filter the names of resolved
+ dependencies. Symlinks are resolved when attempting to match these filenames.
+
+``POST_EXCLUDE_FILES <files>``
+ .. versionadded:: 3.21
+
+ List of post-exclude filenames through which to filter the names of resolved
+ dependencies. Symlinks are resolved when attempting to match these filenames.
+
These arguments can be used to exclude unwanted system libraries when
resolving the dependencies, or to include libraries from a specific
directory. The filtering works as follows:
@@ -288,16 +306,18 @@ directory. The filtering works as follows:
4. ``file(GET_RUNTIME_DEPENDENCIES)`` searches for the dependency according to
the linking rules of the platform (see below).
5. If the dependency is found, and its full path matches one of the
- ``POST_INCLUDE_REGEXES``, the full path is added to the resolved
- dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` recursively resolves
- that library's own dependencies. Otherwise, resolution proceeds to step 6.
+ ``POST_INCLUDE_REGEXES`` or ``POST_INCLUDE_FILES``, the full path is added
+ to the resolved dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)``
+ recursively resolves that library's own dependencies. Otherwise, resolution
+ proceeds to step 6.
6. If the dependency is found, but its full path matches one of the
- ``POST_EXCLUDE_REGEXES``, it is not added to the resolved dependencies, and
- dependency resolution stops for that dependency.
+ ``POST_EXCLUDE_REGEXES`` or ``POST_EXCLUDE_FILES``, it is not added to the
+ resolved dependencies, and dependency resolution stops for that dependency.
7. If the dependency is found, and its full path does not match either
- ``POST_INCLUDE_REGEXES`` or ``POST_EXCLUDE_REGEXES``, the full path is added
- to the resolved dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)``
- recursively resolves that library's own dependencies.
+ ``POST_INCLUDE_REGEXES``, ``POST_INCLUDE_FILES``, ``POST_EXCLUDE_REGEXES``,
+ or ``POST_EXCLUDE_FILES``, the full path is added to the resolved
+ dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` recursively resolves
+ that library's own dependencies.
Different platforms have different rules for how dependencies are resolved.
These specifics are described here.
@@ -675,11 +695,50 @@ Examples of recursive globbing include::
.. code-block:: cmake
- file(RENAME <oldname> <newname>)
+ file(RENAME <oldname> <newname>
+ [RESULT <result>]
+ [NO_REPLACE])
Move a file or directory within a filesystem from ``<oldname>`` to
``<newname>``, replacing the destination atomically.
+The options are:
+
+``RESULT <result>``
+ .. versionadded:: 3.21
+
+ Set ``<result>`` variable to ``0`` on success or an error message otherwise.
+ If ``RESULT`` is not specified and the operation fails, an error is emitted.
+
+``NO_REPLACE``
+ .. versionadded:: 3.21
+
+ If the ``<newname>`` path already exists, do not replace it.
+ If ``RESULT <result>`` is used, the result variable will be
+ set to ``NO_REPLACE``. Otherwise, an error is emitted.
+
+.. _COPY_FILE:
+
+.. code-block:: cmake
+
+ file(COPY_FILE <oldname> <newname>
+ [RESULT <result>]
+ [ONLY_IF_DIFFERENT])
+
+Copy a file from ``<oldname>`` to ``<newname>``. Directories are not
+supported. Symlinks are ignored and ``<oldfile>``'s content is read and
+written to ``<newname>`` as a new file.
+
+The options are:
+
+``RESULT <result>``
+ Set ``<result>`` variable to ``0`` on success or an error message otherwise.
+ If ``RESULT`` is not specified and the operation fails, an error is emitted.
+
+``ONLY_IF_DIFFERENT``
+ If the ``<newname>`` path already exists, do not replace it if it is the
+ same as ``<oldname>``. Otherwise, an error is emitted.
+
.. _REMOVE:
.. _REMOVE_RECURSE:
@@ -888,16 +947,26 @@ Path Conversion
.. code-block:: cmake
- file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>])
+ file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE])
.. versionadded:: 3.19
Compute the absolute path to an existing file or directory with symlinks
resolved.
-If the provided ``<path>`` is a relative path, it is evaluated relative to the
-given base directory ``<dir>``. If no base directory is provided, the default
-base directory will be :variable:`CMAKE_CURRENT_SOURCE_DIR`.
+``BASE_DIRECTORY <dir>``
+ If the provided ``<path>`` is a relative path, it is evaluated relative to the
+ given base directory ``<dir>``. If no base directory is provided, the default
+ base directory will be :variable:`CMAKE_CURRENT_SOURCE_DIR`.
+
+``EXPAND_TILDE``
+ .. versionadded:: 3.21
+
+ If the ``<path>`` is ``~`` or starts with ``~/``, the ``~`` is replaced by
+ the user's home directory. The path to the home directory is obtained from
+ environment variables. On Windows, the ``USERPROFILE`` environment variable
+ is used, falling back to the ``HOME`` environment variable if ``USERPROFILE``
+ is not defined. On all other platforms, only ``HOME`` is used.
.. _RELATIVE_PATH:
@@ -1024,7 +1093,7 @@ If neither ``NETRC`` option is given CMake will check variables
For ``https://`` URLs CMake must be built with OpenSSL support. ``TLS/SSL``
certificates are not checked by default. Set ``TLS_VERIFY`` to ``ON`` to
check certificates. If neither ``TLS`` option is given CMake will check
-variables ``CMAKE_TLS_VERIFY`` and ``CMAKE_TLS_CAINFO``, respectively.
+variables :variable:`CMAKE_TLS_VERIFY` and ``CMAKE_TLS_CAINFO``, respectively.
Additional options to ``DOWNLOAD`` are:
diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst
index 8de6debae..d9f54ca75 100644
--- a/Help/command/foreach.rst
+++ b/Help/command/foreach.rst
@@ -14,9 +14,12 @@ semicolon or whitespace.
All commands between ``foreach`` and the matching ``endforeach`` are recorded
without being invoked. Once the ``endforeach`` is evaluated, the recorded
list of commands is invoked once for each item in ``<items>``.
-At the beginning of each iteration the variable ``loop_var`` will be set
+At the beginning of each iteration the variable ``<loop_var>`` will be set
to the value of the current item.
+The scope of ``<loop_var>`` is restricted to the loop scope. See policy
+:policy:`CMP0124` for details.
+
The commands :command:`break` and :command:`continue` provide means to
escape from the normal control flow.
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 35207f4c4..c6af4897e 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -9,11 +9,13 @@ Synopsis
.. parsed-literal::
install(`TARGETS`_ <target>... [...])
+ install(`IMPORTED_RUNTIME_ARTIFACTS`_ <target>... [...])
install({`FILES`_ | `PROGRAMS`_} <file>... [...])
install(`DIRECTORY`_ <dir>... [...])
install(`SCRIPT`_ <file> [...])
install(`CODE`_ <code> [...])
install(`EXPORT`_ <export-name> [...])
+ install(`RUNTIME_DEPENDENCY_SET`_ <set-name> [...])
Introduction
^^^^^^^^^^^^
@@ -124,6 +126,7 @@ Installing Targets
.. code-block:: cmake
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]
[DESTINATION <dir>]
@@ -338,6 +341,49 @@ top level:
relative path is specified, it is treated as relative to the
``$<INSTALL_PREFIX>``.
+``RUNTIME_DEPENDENCY_SET``
+ .. versionadded:: 3.21
+
+ This option causes all runtime dependencies of installed executable, shared
+ library, and module targets to be added to the specified runtime dependency
+ set. This set can then be installed with an
+ `install(RUNTIME_DEPENDENCY_SET)`_ command.
+
+ This keyword and the ``RUNTIME_DEPENDENCIES`` keyword are mutually
+ exclusive.
+
+``RUNTIME_DEPENDENCIES``
+ .. versionadded:: 3.21
+
+ This option causes all runtime dependencies of installed executable, shared
+ library, and module targets to be installed along with the targets
+ themselves. The ``RUNTIME``, ``LIBRARY``, ``FRAMEWORK``, and generic
+ arguments are used to determine the properties (``DESTINATION``,
+ ``COMPONENT``, etc.) of the installation of these dependencies.
+
+ ``RUNTIME_DEPENDENCIES`` is semantically equivalent to the following pair
+ of calls:
+
+ .. code-block:: cmake
+
+ install(TARGETS ... RUNTIME_DEPENDENCY_SET <set-name>)
+ install(RUNTIME_DEPENDENCY_SET <set-name> args...)
+
+ where ``<set-name>`` will be a randomly generated set name.
+ The ``args...`` may include any of the following keywords supported by
+ the `install(RUNTIME_DEPENDENCY_SET)`_ command:
+
+ * ``DIRECTORIES``
+ * ``PRE_INCLUDE_REGEXES``
+ * ``PRE_EXCLUDE_REGEXES``
+ * ``POST_INCLUDE_REGEXES``
+ * ``POST_EXCLUDE_REGEXES``
+ * ``POST_INCLUDE_FILES``
+ * ``POST_EXCLUDE_FILES``
+
+ The ``RUNTIME_DEPENDENCIES`` and ``RUNTIME_DEPENDENCY_SET`` keywords are
+ mutually exclusive.
+
One or more groups of properties may be specified in a single call to
the ``TARGETS`` form of this command. A target may be installed more than
once to different locations. Consider hypothetical targets ``myExe``,
@@ -382,6 +428,44 @@ set to ``TRUE`` has undefined behavior.
to ensure that such out-of-directory targets are built before the
subdirectory-specific install rules are run.
+Installing Imported Runtime Artifacts
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. _`install(IMPORTED_RUNTIME_ARTIFACTS)`:
+.. _IMPORTED_RUNTIME_ARTIFACTS:
+
+.. versionadded:: 3.21
+
+.. code-block:: cmake
+
+ install(IMPORTED_RUNTIME_ARTIFACTS targets...
+ [RUNTIME_DEPENDENCY_SET <set-name>]
+ [[LIBRARY|RUNTIME|FRAMEWORK|BUNDLE]
+ [DESTINATION <dir>]
+ [PERMISSIONS permissions...]
+ [CONFIGURATIONS [Debug|Release|...]]
+ [COMPONENT <component>]
+ [OPTIONAL] [EXCLUDE_FROM_ALL]
+ ] [...]
+ )
+
+The ``IMPORTED_RUNTIME_ARTIFACTS`` form specifies rules for installing the
+runtime artifacts of imported targets. Projects may do this if they want to
+bundle outside executables or modules inside their installation. The
+``LIBRARY``, ``RUNTIME``, ``FRAMEWORK``, and ``BUNDLE`` arguments have the
+same semantics that they do in the `TARGETS`_ mode. Only the runtime artifacts
+of imported targets are installed (except in the case of :prop_tgt:`FRAMEWORK`
+libraries, :prop_tgt:`MACOSX_BUNDLE` executables, and :prop_tgt:`BUNDLE`
+CFBundles.) For example, headers and import libraries associated with DLLs are
+not installed. In the case of :prop_tgt:`FRAMEWORK` libraries,
+:prop_tgt:`MACOSX_BUNDLE` executables, and :prop_tgt:`BUNDLE` CFBundles, the
+entire directory is installed.
+
+The ``RUNTIME_DEPENDENCY_SET`` option causes the runtime artifacts of the
+imported executable, shared library, and module library ``targets`` to be
+added to the ``<set-name>`` runtime dependency set. This set can then be
+installed with an `install(RUNTIME_DEPENDENCY_SET)`_ command.
+
Installing Files
^^^^^^^^^^^^^^^^
@@ -540,7 +624,8 @@ any expression. For example, the code
will extract and install header files from a source tree.
-Some options may follow a ``PATTERN`` or ``REGEX`` expression and are applied
+Some options may follow a ``PATTERN`` or ``REGEX`` expression as described
+under :ref:`string(REGEX) <Regex Specification>` and are applied
only to files or directories matching them. The ``EXCLUDE`` option will
skip the matched file or directory. The ``PERMISSIONS`` option overrides
the permissions setting for the matched file or directory. For
@@ -619,7 +704,8 @@ Custom Installation Logic
.. code-block:: cmake
install([[SCRIPT <file>] [CODE <code>]]
- [COMPONENT <component>] [EXCLUDE_FROM_ALL] [...])
+ [ALL_COMPONENTS | COMPONENT <component>]
+ [EXCLUDE_FROM_ALL] [...])
The ``SCRIPT`` form will invoke the given CMake script files during
installation. If the script file name is a relative path it will be
@@ -634,6 +720,12 @@ example, the code
will print a message during installation.
+.. versionadded:: 3.21
+ When the ``ALL_COMPONENTS`` option is given, the custom installation
+ script code will be executed for every component of a component-specific
+ installation. This option is mutually exclusive with the ``COMPONENT``
+ option.
+
.. versionadded:: 3.14
``<file>`` or ``<code>`` may use "generator expressions" with the syntax
``$<...>`` (in the case of ``<file>``, this refers to their use in the file
@@ -724,7 +816,7 @@ executable from the installation tree using the imported target name
``mp_myexe`` as if the target were built in its own tree.
.. note::
- This command supercedes the :command:`install_targets` command and
+ This command supersedes the :command:`install_targets` command and
the :prop_tgt:`PRE_INSTALL_SCRIPT` and :prop_tgt:`POST_INSTALL_SCRIPT`
target properties. It also replaces the ``FILES`` forms of the
:command:`install_files` and :command:`install_programs` commands.
@@ -733,6 +825,70 @@ executable from the installation tree using the imported target name
:command:`install_files`, and :command:`install_programs` commands
is not defined.
+Installing Runtime Dependencies
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. _`install(RUNTIME_DEPENDENCY_SET)`:
+.. _RUNTIME_DEPENDENCY_SET:
+
+.. versionadded:: 3.21
+
+.. code-block:: cmake
+
+ install(RUNTIME_DEPENDENCY_SET <set-name>
+ [[LIBRARY|RUNTIME|FRAMEWORK]
+ [DESTINATION <dir>]
+ [PERMISSIONS permissions...]
+ [CONFIGURATIONS [Debug|Release|...]]
+ [COMPONENT <component>]
+ [NAMELINK_COMPONENT <component>]
+ [OPTIONAL] [EXCLUDE_FROM_ALL]
+ ] [...]
+ [PRE_INCLUDE_REGEXES regexes...]
+ [PRE_EXCLUDE_REGEXES regexes...]
+ [POST_INCLUDE_REGEXES regexes...]
+ [POST_EXCLUDE_REGEXES regexes...]
+ [POST_INCLUDE_FILES files...]
+ [POST_EXCLUDE_FILES files...]
+ [DIRECTORIES directories...]
+ )
+
+Installs a runtime dependency set previously created by one or more
+`install(TARGETS)`_ or `install(IMPORTED_RUNTIME_ARTIFACTS)`_ commands. The
+dependencies of targets belonging to a runtime dependency set are installed in
+the ``RUNTIME`` destination and component on DLL platforms, and in the
+``LIBRARY`` destination and component on non-DLL platforms. macOS frameworks
+are installed in the ``FRAMEWORK`` destination and component.
+Targets built within the build tree will never be installed as runtime
+dependencies, nor will their own dependencies, unless the targets themselves
+are installed with `install(TARGETS)`_.
+
+The generated install script calls :command:`file(GET_RUNTIME_DEPENDENCIES)`
+on the build-tree files to calculate the runtime dependencies. The build-tree
+executable files are passed as the ``EXECUTABLES`` argument, the build-tree
+shared libraries as the ``LIBRARIES`` argument, and the build-tree modules as
+the ``MODULES`` argument. On macOS, if one of the executables is a
+:prop_tgt:`MACOSX_BUNDLE`, that executable is passed as the
+``BUNDLE_EXECUTABLE`` argument. At most one such bundle executable may be in
+the runtime dependency set on macOS. The :prop_tgt:`MACOSX_BUNDLE` property
+has no effect on other platforms. Note that
+:command:`file(GET_RUNTIME_DEPENDENCIES)` only supports collecting the runtime
+dependencies for Windows, Linux and macOS platforms, so
+``install(RUNTIME_DEPENDENCY_SET)`` has the same limitation.
+
+The following sub-arguments are forwarded through as the corresponding
+arguments to :command:`file(GET_RUNTIME_DEPENDENCIES)` (for those that provide
+a non-empty list of directories, regular expressions or files). They all
+support :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+* ``DIRECTORIES <directories>``
+* ``PRE_INCLUDE_REGEXES <regexes>``
+* ``PRE_EXCLUDE_REGEXES <regexes>``
+* ``POST_INCLUDE_REGEXES <regexes>``
+* ``POST_EXCLUDE_REGEXES <regexes>``
+* ``POST_INCLUDE_FILES <files>``
+* ``POST_EXCLUDE_FILES <files>``
+
Generated Installation Script
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Help/command/install_files.rst b/Help/command/install_files.rst
index ff074a8a7..494f3d0ee 100644
--- a/Help/command/install_files.rst
+++ b/Help/command/install_files.rst
@@ -5,7 +5,7 @@ install_files
Use the :command:`install(FILES)` command instead.
-This command has been superceded by the :command:`install` command. It is
+This command has been superseded by the :command:`install` command. It is
provided for compatibility with older CMake code. The ``FILES`` form is
directly replaced by the ``FILES`` form of the :command:`install`
command. The regexp form can be expressed more clearly using the ``GLOB``
diff --git a/Help/command/install_programs.rst b/Help/command/install_programs.rst
index fab64820d..eafae8996 100644
--- a/Help/command/install_programs.rst
+++ b/Help/command/install_programs.rst
@@ -5,7 +5,7 @@ install_programs
Use the :command:`install(PROGRAMS)` command instead.
-This command has been superceded by the :command:`install` command. It is
+This command has been superseded by the :command:`install` command. It is
provided for compatibility with older CMake code. The ``FILES`` form is
directly replaced by the ``PROGRAMS`` form of the :command:`install`
command. The regexp form can be expressed more clearly using the ``GLOB``
diff --git a/Help/command/install_targets.rst b/Help/command/install_targets.rst
index c9efdce67..9355f8d53 100644
--- a/Help/command/install_targets.rst
+++ b/Help/command/install_targets.rst
@@ -5,7 +5,7 @@ install_targets
Use the :command:`install(TARGETS)` command instead.
-This command has been superceded by the :command:`install` command. It is
+This command has been superseded by the :command:`install` command. It is
provided for compatibility with older CMake code.
::
diff --git a/Help/command/list.rst b/Help/command/list.rst
index 7accc5a39..f46641f0b 100644
--- a/Help/command/list.rst
+++ b/Help/command/list.rst
@@ -141,8 +141,8 @@ Appends elements to the list.
Includes or removes items from the list that match the mode's pattern.
In ``REGEX`` mode, items will be matched against the given regular expression.
-For more information on regular expressions see also the
-:command:`string` command.
+For more information on regular expressions look under
+:ref:`string(REGEX) <Regex Specification>`.
.. _INSERT:
diff --git a/Help/command/project.rst b/Help/command/project.rst
index 6c931b692..2a9dcfe30 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -20,12 +20,18 @@ Sets the name of the project, and stores it in the variable
``CMakeLists.txt`` also stores the project name in the
variable :variable:`CMAKE_PROJECT_NAME`.
-Also sets the variables
+Also sets the variables:
-* :variable:`PROJECT_SOURCE_DIR`,
- :variable:`<PROJECT-NAME>_SOURCE_DIR`
-* :variable:`PROJECT_BINARY_DIR`,
- :variable:`<PROJECT-NAME>_BINARY_DIR`
+:variable:`PROJECT_SOURCE_DIR`, :variable:`<PROJECT-NAME>_SOURCE_DIR`
+ Absolute path to the source directory for the project.
+
+:variable:`PROJECT_BINARY_DIR`, :variable:`<PROJECT-NAME>_BINARY_DIR`
+ Absolute path to the binary directory for the project.
+
+:variable:`PROJECT_IS_TOP_LEVEL`, :variable:`<PROJECT-NAME>_IS_TOP_LEVEL`
+ .. versionadded:: 3.21
+
+ Boolean value indicating whether the project is top-level.
Further variables are set by the optional arguments described in the following.
If any of these arguments is not used, then the corresponding variables are
@@ -97,7 +103,7 @@ The options are:
Selects which programming languages are needed to build the project.
Supported languages include ``C``, ``CXX`` (i.e. C++), ``CUDA``,
- ``OBJC`` (i.e. Objective-C), ``OBJCXX``, ``Fortran``, ``ISPC``, and ``ASM``.
+ ``OBJC`` (i.e. Objective-C), ``OBJCXX``, ``Fortran``, ``HIP``, ``ISPC``, and ``ASM``.
By default ``C`` and ``CXX`` are enabled if no language options are given.
Specify language ``NONE``, or use the ``LANGUAGES`` keyword and list no languages,
to skip enabling any languages.
diff --git a/Help/command/set.rst b/Help/command/set.rst
index c0e02e246..af862e4da 100644
--- a/Help/command/set.rst
+++ b/Help/command/set.rst
@@ -68,9 +68,13 @@ users.
If the cache entry does not exist prior to the call or the ``FORCE``
option is given then the cache entry will be set to the given value.
-Furthermore, any normal variable binding in the current scope will
-be removed to expose the newly cached value to any immediately
-following evaluation.
+
+.. note::
+
+ The content of the cache variable will not be directly accessible if a normal
+ variable of the same name already exists (see :ref:`rules of variable
+ evaluation <CMake Language Variables>`). If policy :policy:`CMP0126` is set
+ to ``OLD``, any normal variable binding in the current scope will be removed.
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
diff --git a/Help/command/source_group.rst b/Help/command/source_group.rst
index 5db1ec8c5..a4b5bf1c6 100644
--- a/Help/command/source_group.rst
+++ b/Help/command/source_group.rst
@@ -11,6 +11,9 @@ There are two different signatures to create source groups.
Defines a group into which sources will be placed in project files.
This is intended to set up file tabs in Visual Studio.
+The group is scoped in the directory where the command is called,
+and applies to sources in targets created in that directory.
+
The options are:
``TREE``
diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst
index 872e264e9..ac231bc8f 100644
--- a/Help/command/target_link_libraries.rst
+++ b/Help/command/target_link_libraries.rst
@@ -289,6 +289,91 @@ treated as :ref:`Interface Libraries`, but when they appear in
a target's :prop_tgt:`LINK_LIBRARIES` property their object files
will be included in the link too.
+.. _`Linking Object Libraries via $<TARGET_OBJECTS>`:
+
+Linking Object Libraries via $<TARGET_OBJECTS>
+""""""""""""""""""""""""""""""""""""""""""""""
+
+.. versionadded:: 3.21
+
+The object files associated with an object library may be referenced
+by the :genex:`$<TARGET_OBJECTS>` generator expression. Such object
+files are placed on the link line *before* all libraries, regardless
+of their relative order. Additionally, an ordering dependency will be
+added to the build sysstem to make sure the object library is up-to-date
+before the dependent target links. For example, the code
+
+.. code-block:: cmake
+
+ add_library(obj3 OBJECT obj3.c)
+ target_compile_definitions(obj3 PUBLIC OBJ3)
+
+ add_executable(main3 main3.c)
+ target_link_libraries(main3 PRIVATE a3 $<TARGET_OBJECTS:obj3> b3)
+
+links executable ``main3`` with object files from ``main3.c``
+and ``obj3.c`` followed by the ``a3`` and ``b3`` libraries.
+``main3.c`` is *not* compiled with usage requirements from ``obj3``,
+such as ``-DOBJ3``.
+
+This approach can be used to achieve transitive inclusion of object
+files in link lines as usage requirements. Continuing the above
+example, the code
+
+.. code-block:: cmake
+
+ add_library(iface_obj3 INTERFACE)
+ target_link_libraries(iface_obj3 INTERFACE obj3 $<TARGET_OBJECTS:obj3>)
+
+creates an interface library ``iface_obj3`` that forwards the ``obj3``
+usage requirements and adds the ``obj3`` object files to dependents'
+link lines. The code
+
+.. code-block:: cmake
+
+ add_executable(use_obj3 use_obj3.c)
+ target_link_libraries(use_obj3 PRIVATE iface_obj3)
+
+compiles ``use_obj3.c`` with ``-DOBJ3`` and links executable ``use_obj3``
+with object files from ``use_obj3.c`` and ``obj3.c``.
+
+This also works transitively through a static library. Since a static
+library does not link, it does not consume the object files from
+object libraries referenced this way. Instead, the object files
+become transitive link dependencies of the static library.
+Continuing the above example, the code
+
+.. code-block:: cmake
+
+ add_library(static3 STATIC static3.c)
+ target_link_libraries(static3 PRIVATE iface_obj3)
+
+ add_executable(use_static3 use_static3.c)
+ target_link_libraries(use_static3 PRIVATE static3)
+
+compiles ``static3.c`` with ``-DOBJ3`` and creates ``libstatic3.a``
+using only its own object file. ``use_static3.c`` is compiled *without*
+``-DOBJ3`` because the usage requirement is not transitive through
+the private dependency of ``static3``. However, the link dependencies
+of ``static3`` are propagated, including the ``iface_obj3`` reference
+to ``$<TARGET_OBJECTS:obj3>``. The ``use_static3`` executable is
+created with object files from ``use_static3.c`` and ``obj3.c``, and
+linked to library ``libstatic3.a``.
+
+When using this approach, it is the project's responsibility to avoid
+linking multiple dependent binaries to ``iface_obj3``, because they will
+all get the ``obj3`` object files on their link lines.
+
+.. note::
+
+ Referencing :genex:`$<TARGET_OBJECTS>` in ``target_link_libraries``
+ calls worked in versions of CMake prior to 3.21 for some cases,
+ but was not fully supported:
+
+ * It did not place the object files before libraries on link lines.
+ * It did not add an ordering dependency on the object library.
+ * It did not work in Xcode with multiple architectures.
+
Cyclic Dependencies of Static Libraries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Help/cpack_gen/archive.rst b/Help/cpack_gen/archive.rst
index b9418126f..47e8e1354 100644
--- a/Help/cpack_gen/archive.rst
+++ b/Help/cpack_gen/archive.rst
@@ -82,7 +82,8 @@ CPack generators which are essentially archives at their core. These include:
See also the :variable:`CPACK_THREADS` variable.
-.. note::
+ .. versionadded:: 3.21
- Official CMake binaries available on ``cmake.org`` ship with a ``liblzma``
- that does not support parallel compression.
+ Official CMake binaries available on ``cmake.org`` now ship
+ with a ``liblzma`` that supports parallel compression.
+ Older versions did not.
diff --git a/Help/cpack_gen/deb.rst b/Help/cpack_gen/deb.rst
index 03c4ea8db..d8d53ece3 100644
--- a/Help/cpack_gen/deb.rst
+++ b/Help/cpack_gen/deb.rst
@@ -289,7 +289,7 @@ List of CPack DEB generator specific variables:
* Default : "optional"
.. versionadded:: 3.5
- Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_PRIORITY`` varables.
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_PRIORITY`` variables.
See https://www.debian.org/doc/debian-policy/ch-archive.html#s-priorities
diff --git a/Help/cpack_gen/dmg.rst b/Help/cpack_gen/dmg.rst
index 4c662a6f8..64e976998 100644
--- a/Help/cpack_gen/dmg.rst
+++ b/Help/cpack_gen/dmg.rst
@@ -51,7 +51,7 @@ on macOS:
.. versionadded:: 3.6
- Default behaviour is to include a symlink to ``/Applications`` in the DMG.
+ Default behavior is to include a symlink to ``/Applications`` in the DMG.
Set this option to ``ON`` to avoid adding the symlink.
.. variable:: CPACK_DMG_SLA_DIR
@@ -103,6 +103,12 @@ on macOS:
- Default: ``CPACK_PACKAGE_FILE_NAME-<component>``
+.. variable:: CPACK_DMG_FILESYSTEM
+
+ The filesystem format. Common values are ``APFS`` and ``HFS+``.
+ See ``man hdiutil`` for a full list of supported formats.
+ Defaults to ``HFS+``.
+
.. variable:: CPACK_COMMAND_HDIUTIL
Path to the ``hdiutil(1)`` command used to operate on disk image files on
diff --git a/Help/cpack_gen/freebsd.rst b/Help/cpack_gen/freebsd.rst
index 2c9356956..f429bc5fa 100644
--- a/Help/cpack_gen/freebsd.rst
+++ b/Help/cpack_gen/freebsd.rst
@@ -74,7 +74,7 @@ the RPM information (e.g. package license).
* Default:
- :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` (this may be set already
- for Debian packaging, so we may as well re-use it).
+ for Debian packaging, so it is used as a fallback).
.. variable:: CPACK_FREEBSD_PACKAGE_WWW
@@ -87,7 +87,7 @@ the RPM information (e.g. package license).
- :variable:`CMAKE_PROJECT_HOMEPAGE_URL`, or if that is not set,
:variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
- for Debian packaging, so we may as well re-use it).
+ for Debian packaging, so it is used as a fallback).
.. versionadded:: 3.12
The ``CMAKE_PROJECT_HOMEPAGE_URL`` variable.
diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst
index de1f3b5fb..02e33ba30 100644
--- a/Help/cpack_gen/nsis.rst
+++ b/Help/cpack_gen/nsis.rst
@@ -195,3 +195,9 @@ on Windows Nullsoft Scriptable Install System.
If set, trim down the size of the control to the size of the branding text string.
Allowed values for this variable are ``LEFT``, ``CENTER`` or ``RIGHT``.
If not specified, the default behavior is ``LEFT``.
+
+.. variable:: CPACK_NSIS_EXECUTABLE
+
+ .. versionadded:: 3.21
+
+ If set, specify the name of the NSIS executable. Default is ``makensis``.
diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst
index 5260a1d7c..322ab68aa 100644
--- a/Help/cpack_gen/rpm.rst
+++ b/Help/cpack_gen/rpm.rst
@@ -394,8 +394,10 @@ List of CPack RPM generator specific variables:
* Mandatory : NO
* Default : -
- May be used to set weak RPM dependencies (suggests). Note that you must
- enclose the complete requires string between quotes.
+ May be used to set weak RPM dependencies (suggests). If ``rpmbuild`` doesn't
+ support the ``Suggests`` tag, CPack will emit a warning and ignore this
+ variable. Note that you must enclose the complete requires string between
+ quotes.
.. variable:: CPACK_RPM_PACKAGE_PROVIDES
CPACK_RPM_<component>_PACKAGE_PROVIDES
diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst
index d0191615a..2380de4b7 100644
--- a/Help/dev/experimental.rst
+++ b/Help/dev/experimental.rst
@@ -39,7 +39,7 @@ to the file specified by the ``<DEP_FILE>`` placeholder, and write module
dependencies to the file specified by the ``<DYNDEP_FILE>`` placeholder.
The module dependencies should be written in the format described
-by the `P1689r3`_ paper.
+by the `P1689r4`_ paper.
Compiler writers may try out their scanning functionality using
the `cxx-modules-sandbox`_ test project, modified to set variables
@@ -66,5 +66,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
-.. _`P1689r3`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1689r3.html
+.. _`P1689r4`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1689r4.html
.. _`cxx-modules-sandbox`: https://github.com/mathstuf/cxx-modules-sandbox
diff --git a/Help/dev/review.rst b/Help/dev/review.rst
index 8326e7015..198e100a9 100644
--- a/Help/dev/review.rst
+++ b/Help/dev/review.rst
@@ -20,8 +20,10 @@ creating a *merge request* ("MR"). The new MR will appear on the
process is managed by the merge request page for the change.
During the review process, the MR submitter should address review comments
-or test failures by updating the MR with a (force-)push of the topic
-branch. The update initiates a new round of review.
+or test failures by updating their local topic branch to fix their commits
+(e.g. via ``git commit --amend`` or ``git rebase -i``), and then issuing a
+(force-)push of the topic branch to their remote (e.g. ``git push --force``).
+This will automatically initiate a new round of review on the existing MR.
We recommend that users enable the "Remove source branch when merge
request is accepted" option when creating the MR or by editing it.
@@ -254,7 +256,8 @@ The preferred form for references to other commits is
The author date of the commit, in its original time zone, formatted as
``CCYY-MM-DD``. ``git-log(1)`` shows the original time zone by default.
-This may be generated with
+This may be generated with ``git show -s --pretty=reference <commit>`` with
+Git 2.25 and newer. Older versions of Git can generate the same format via
``git show -s --date=short --pretty="format:%h (%s, %ad)" <commit>``.
If the commit is a fix for the mentioned commit, consider using a ``Fixes:``
diff --git a/Help/envvar/CMAKE_LANG_LINKER_LAUNCHER.rst b/Help/envvar/CMAKE_LANG_LINKER_LAUNCHER.rst
new file mode 100644
index 000000000..6251d9c75
--- /dev/null
+++ b/Help/envvar/CMAKE_LANG_LINKER_LAUNCHER.rst
@@ -0,0 +1,13 @@
+CMAKE_<LANG>_LINKER_LAUNCHER
+----------------------------
+
+.. versionadded:: 3.21
+
+.. include:: ENV_VAR.txt
+
+Default launcher to use when linking a target of the specified language. Will
+only be used by CMake to initialize the variable on the first configuration.
+Afterwards, it is available through the cache setting of the variable of the
+same name. For any configuration run (including the first), the environment
+variable will be ignored if the :variable:`CMAKE_<LANG>_LINKER_LAUNCHER`
+variable is defined.
diff --git a/Help/envvar/CMAKE_TOOLCHAIN_FILE.rst b/Help/envvar/CMAKE_TOOLCHAIN_FILE.rst
new file mode 100644
index 000000000..7ea9cea35
--- /dev/null
+++ b/Help/envvar/CMAKE_TOOLCHAIN_FILE.rst
@@ -0,0 +1,12 @@
+CMAKE_TOOLCHAIN_FILE
+--------------------
+
+.. versionadded:: 3.21
+
+.. include:: ENV_VAR.txt
+
+The ``CMAKE_TOOLCHAIN_FILE`` environment variable specifies a default value
+for the :variable:`CMAKE_TOOLCHAIN_FILE` variable when there is no explicit
+configuration given on the first run while creating a new build tree.
+On later runs in an existing build tree the value persists in the cache
+as :variable:`CMAKE_TOOLCHAIN_FILE`.
diff --git a/Help/envvar/CUDAHOSTCXX.rst b/Help/envvar/CUDAHOSTCXX.rst
index 963f9d113..cf65927a5 100644
--- a/Help/envvar/CUDAHOSTCXX.rst
+++ b/Help/envvar/CUDAHOSTCXX.rst
@@ -15,6 +15,10 @@ ignored if the :variable:`CMAKE_CUDA_HOST_COMPILER` variable is defined.
This environment variable is primarily meant for use with projects that
enable ``CUDA`` as a first-class language.
+.. note::
+
+ Ignored when using :ref:`Visual Studio Generators`.
+
.. versionadded:: 3.13
The :module:`FindCUDA`
module will use this variable to initialize its ``CUDA_HOST_COMPILER`` setting.
diff --git a/Help/envvar/HIPCXX.rst b/Help/envvar/HIPCXX.rst
new file mode 100644
index 000000000..23329e978
--- /dev/null
+++ b/Help/envvar/HIPCXX.rst
@@ -0,0 +1,13 @@
+HIPCXX
+------
+
+.. versionadded:: 3.21
+
+.. include:: ENV_VAR.txt
+
+Preferred executable for compiling ``HIP`` language files. Will only be used by
+CMake on the first configuration to determine ``HIP`` compiler, after which the
+value for ``HIP`` is stored in the cache as
+:variable:`CMAKE_HIP_COMPILER <CMAKE_<LANG>_COMPILER>`. For any configuration
+run (including the first), the environment variable will be ignored if the
+:variable:`CMAKE_HIP_COMPILER <CMAKE_<LANG>_COMPILER>` variable is defined.
diff --git a/Help/envvar/HIPFLAGS.rst b/Help/envvar/HIPFLAGS.rst
new file mode 100644
index 000000000..0df3416e2
--- /dev/null
+++ b/Help/envvar/HIPFLAGS.rst
@@ -0,0 +1,15 @@
+HIPFLAGS
+--------
+
+.. versionadded:: 3.21
+
+.. 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.
+
+See also :variable:`CMAKE_HIP_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`.
diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst
index 89011925f..e5ce4f5cd 100644
--- a/Help/generator/Ninja Multi-Config.rst
+++ b/Help/generator/Ninja Multi-Config.rst
@@ -34,7 +34,9 @@ below for how to enable cross-config mode.
The ``Ninja Multi-Config`` generator recognizes the following variables:
:variable:`CMAKE_CONFIGURATION_TYPES`
- Specifies the total set of configurations to build.
+ Specifies the total set of configurations to build. Unlike with other
+ multi-config generators, this variable has a value of
+ ``Debug;Release;RelWithDebInfo`` by default.
:variable:`CMAKE_CROSS_CONFIGS`
Specifies a :ref:`semicolon-separated list <CMake Language Lists>` of
diff --git a/Help/generator/VS_TOOLSET_HOST_ARCH.txt b/Help/generator/VS_TOOLSET_HOST_ARCH.txt
index e36171999..029363115 100644
--- a/Help/generator/VS_TOOLSET_HOST_ARCH.txt
+++ b/Help/generator/VS_TOOLSET_HOST_ARCH.txt
@@ -1,11 +1,7 @@
-.. versionadded:: 3.8
- For each toolset that comes with this version of Visual Studio, there are
- variants that are themselves compiled for 32-bit (``x86``) and
- 64-bit (``x64``) hosts (independent of the architecture they target).
- |VS_TOOLSET_HOST_ARCH_DEFAULT|
- One may explicitly request use of either the 32-bit or 64-bit host tools
- by adding either ``host=x86`` or ``host=x64`` to the toolset specification.
- See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details.
-
-.. versionadded:: 3.14
- Added suport for ``host=x86`` option.
+For each toolset that comes with this version of Visual Studio, there are
+variants that are themselves compiled for 32-bit (``x86``) and
+64-bit (``x64``) hosts (independent of the architecture they target).
+|VS_TOOLSET_HOST_ARCH_DEFAULT|
+One may explicitly request use of either the 32-bit or 64-bit host tools
+by adding either ``host=x86`` or ``host=x64`` to the toolset specification.
+See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details.
diff --git a/Help/generator/VS_TOOLSET_HOST_ARCH_LEGACY.txt b/Help/generator/VS_TOOLSET_HOST_ARCH_LEGACY.txt
new file mode 100644
index 000000000..069638bd2
--- /dev/null
+++ b/Help/generator/VS_TOOLSET_HOST_ARCH_LEGACY.txt
@@ -0,0 +1,11 @@
+.. versionadded:: 3.8
+ For each toolset that comes with this version of Visual Studio, there are
+ variants that are themselves compiled for 32-bit (``x86``) and
+ 64-bit (``x64``) hosts (independent of the architecture they target).
+ |VS_TOOLSET_HOST_ARCH_DEFAULT|
+ One may explicitly request use of either the 32-bit or 64-bit host tools
+ by adding either ``host=x86`` or ``host=x64`` to the toolset specification.
+ See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details.
+
+.. versionadded:: 3.14
+ Added support for ``host=x86`` option.
diff --git a/Help/generator/Visual Studio 10 2010.rst b/Help/generator/Visual Studio 10 2010.rst
index b4376d88b..c06555036 100644
--- a/Help/generator/Visual Studio 10 2010.rst
+++ b/Help/generator/Visual Studio 10 2010.rst
@@ -9,8 +9,9 @@ generator using the name ``Visual Studio 10`` without the year component.
Project Types
^^^^^^^^^^^^^
-Only Visual C++ and C# projects may be generated. Other types of
-projects (Database, Website, etc.) are not supported.
+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
^^^^^^^^^^^^^^^^^^
diff --git a/Help/generator/Visual Studio 11 2012.rst b/Help/generator/Visual Studio 11 2012.rst
index 932548bd2..3952228fe 100644
--- a/Help/generator/Visual Studio 11 2012.rst
+++ b/Help/generator/Visual Studio 11 2012.rst
@@ -9,8 +9,9 @@ generator using the name "Visual Studio 11" without the year component.
Project Types
^^^^^^^^^^^^^
-Only Visual C++ and C# projects may be generated. Other types of
-projects (JavaScript, Database, Website, etc.) are not supported.
+Only Visual C++ and C# projects may be generated (and Fortran with
+Intel compiler integration). Other types of projects (JavaScript,
+Database, Website, etc.) are not supported.
Platform Selection
^^^^^^^^^^^^^^^^^^
diff --git a/Help/generator/Visual Studio 12 2013.rst b/Help/generator/Visual Studio 12 2013.rst
index b5fa1bf49..54a4d7eb9 100644
--- a/Help/generator/Visual Studio 12 2013.rst
+++ b/Help/generator/Visual Studio 12 2013.rst
@@ -9,8 +9,9 @@ generator using the name "Visual Studio 12" without the year component.
Project Types
^^^^^^^^^^^^^
-Only Visual C++ and C# projects may be generated. Other types of
-projects (JavaScript, Powershell, Python, etc.) are not supported.
+Only Visual C++ and C# projects may be generated (and Fortran with
+Intel compiler integration). Other types of projects (JavaScript,
+Powershell, Python, etc.) are not supported.
Platform Selection
^^^^^^^^^^^^^^^^^^
@@ -46,4 +47,4 @@ via the :manual:`cmake(1)` ``-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.
-.. include:: VS_TOOLSET_HOST_ARCH.txt
+.. include:: VS_TOOLSET_HOST_ARCH_LEGACY.txt
diff --git a/Help/generator/Visual Studio 14 2015.rst b/Help/generator/Visual Studio 14 2015.rst
index 9c616414f..d704ab271 100644
--- a/Help/generator/Visual Studio 14 2015.rst
+++ b/Help/generator/Visual Studio 14 2015.rst
@@ -8,8 +8,9 @@ Generates Visual Studio 14 (VS 2015) project files.
Project Types
^^^^^^^^^^^^^
-Only Visual C++ and C# projects may be generated. Other types of
-projects (JavaScript, Powershell, Python, etc.) are not supported.
+Only Visual C++ and C# projects may be generated (and Fortran with
+Intel compiler integration). Other types of projects (JavaScript,
+Powershell, Python, etc.) are not supported.
Platform Selection
^^^^^^^^^^^^^^^^^^
@@ -44,7 +45,7 @@ via the :manual:`cmake(1)` ``-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.
-.. include:: VS_TOOLSET_HOST_ARCH.txt
+.. include:: VS_TOOLSET_HOST_ARCH_LEGACY.txt
.. _`Windows 10 SDK Maximum Version for VS 2015`:
diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst
index a002f2ff6..a4f5f98e3 100644
--- a/Help/generator/Visual Studio 15 2017.rst
+++ b/Help/generator/Visual Studio 15 2017.rst
@@ -8,8 +8,9 @@ Generates Visual Studio 15 (VS 2017) project files.
Project Types
^^^^^^^^^^^^^
-Only Visual C++ and C# projects may be generated. Other types of
-projects (JavaScript, Powershell, Python, etc.) are not supported.
+Only Visual C++ and C# projects may be generated (and Fortran with
+Intel compiler integration). Other types of projects (JavaScript,
+Powershell, Python, etc.) are not supported.
Instance Selection
^^^^^^^^^^^^^^^^^^
@@ -63,4 +64,4 @@ via the :manual:`cmake(1)` ``-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.
-.. include:: VS_TOOLSET_HOST_ARCH.txt
+.. include:: VS_TOOLSET_HOST_ARCH_LEGACY.txt
diff --git a/Help/generator/Visual Studio 16 2019.rst b/Help/generator/Visual Studio 16 2019.rst
index 3da80915a..72399e0a2 100644
--- a/Help/generator/Visual Studio 16 2019.rst
+++ b/Help/generator/Visual Studio 16 2019.rst
@@ -8,8 +8,9 @@ Generates Visual Studio 16 (VS 2019) project files.
Project Types
^^^^^^^^^^^^^
-Only Visual C++ and C# projects may be generated. Other types of
-projects (JavaScript, Powershell, Python, etc.) are not supported.
+Only Visual C++ and C# projects may be generated (and Fortran with
+Intel compiler integration). Other types of projects (JavaScript,
+Powershell, Python, etc.) are not supported.
Instance Selection
^^^^^^^^^^^^^^^^^^
diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst
new file mode 100644
index 000000000..06deda463
--- /dev/null
+++ b/Help/generator/Visual Studio 17 2022.rst
@@ -0,0 +1,62 @@
+Visual Studio 17 2022
+---------------------
+
+.. versionadded:: 3.21
+
+Generates Visual Studio 17 (VS 2022) project files.
+
+.. warning::
+
+ This is experimental and based on "Visual Studio 2022 Preview 1.1".
+ As of this version of CMake, VS 2022 has not been released.
+
+Project Types
+^^^^^^^^^^^^^
+
+Only Visual C++ and C# projects may be generated (and Fortran with
+Intel compiler integration). Other types of projects (JavaScript,
+Powershell, Python, etc.) are not supported.
+
+Instance Selection
+^^^^^^^^^^^^^^^^^^
+
+VS 2022 supports multiple installations on the same machine.
+The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a
+cache entry containing the absolute path to a Visual Studio instance.
+If the value is not specified explicitly by the user or a toolchain file,
+CMake queries the Visual Studio Installer to locate VS instances, chooses
+one, and sets the variable as a cache entry to hold the value persistently.
+
+When CMake first chooses an instance, if the ``VS170COMNTOOLS`` environment
+variable is set and points to the ``Common7/Tools`` directory within
+one of the instances, that instance will be used. Otherwise, if more
+than one instance is installed we do not define which one is chosen
+by default.
+
+Platform Selection
+^^^^^^^^^^^^^^^^^^
+
+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
+name (architecture). For example:
+
+* ``cmake -G "Visual Studio 17 2022" -A Win32``
+* ``cmake -G "Visual Studio 17 2022" -A x64``
+* ``cmake -G "Visual Studio 17 2022" -A ARM``
+* ``cmake -G "Visual Studio 17 2022" -A ARM64``
+
+Toolset Selection
+^^^^^^^^^^^^^^^^^
+
+The ``v142`` toolset that comes with VS 17 2022 Preview 1.1 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.
+
+.. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace::
+ By default this generator uses the 64-bit variant on x64 hosts and
+ the 32-bit variant otherwise.
+
+.. include:: VS_TOOLSET_HOST_ARCH.txt
diff --git a/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt
index 9a9e40ee2..d277b5419 100644
--- a/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt
+++ b/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.15)
project(MathFunctions)
+# make cache variables for install destinations
+include(GNUInstallDirs)
+
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
@@ -12,26 +15,26 @@ add_library(MathFunctions STATIC MathFunctions.cxx)
target_include_directories(MathFunctions
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
- "$<INSTALL_INTERFACE:include>"
+ "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
# install the target and create export-set
install(TARGETS MathFunctions
EXPORT MathFunctionsTargets
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib
- RUNTIME DESTINATION bin
- INCLUDES DESTINATION include
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
# install header file
-install(FILES MathFunctions.h DESTINATION include)
+install(FILES MathFunctions.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# generate and install export file
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
NAMESPACE MathFunctions::
- DESTINATION lib/cmake/MathFunctions
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions
)
# include CMakePackageConfigHelpers macro
@@ -58,14 +61,14 @@ write_basic_package_version_file(
# create config file
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
- INSTALL_DESTINATION lib/cmake/MathFunctions
+ INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions
)
# install config files
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
- DESTINATION lib/cmake/MathFunctions
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions
)
# generate the export targets for the build tree
diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt
index 17ad95210..9de935eea 100644
--- a/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt
+++ b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt
@@ -7,24 +7,24 @@ add_library(MathFunctions::Addition ALIAS Addition)
target_include_directories(Addition
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
- $<INSTALL_INTERFACE:include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
# install the target and create export-set
install(TARGETS Addition
EXPORT AdditionTargets
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib
- RUNTIME DESTINATION bin
- INCLUDES DESTINATION include
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
# install header file
-install(FILES Addition.h DESTINATION include)
+install(FILES Addition.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# generate and install export file
install(EXPORT AdditionTargets
FILE MathFunctionsAdditionTargets.cmake
NAMESPACE MathFunctions::
- DESTINATION lib/cmake/MathFunctions
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions
)
diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt
index fd95e28df..90ee89f0f 100644
--- a/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt
+++ b/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.15)
project(MathFunctionsComponents)
+# make cache variables for install destinations
+include(GNUInstallDirs)
+
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
@@ -24,7 +27,7 @@ write_basic_package_version_file(
# create config file
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
- INSTALL_DESTINATION lib/cmake/MathFunctions
+ INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
@@ -32,5 +35,5 @@ configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
- DESTINATION lib/cmake/MathFunctions
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions
)
diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt
index be5ae65d1..517c5e26a 100644
--- a/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt
+++ b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt
@@ -7,24 +7,24 @@ add_library(MathFunctions::SquareRoot ALIAS SquareRoot)
target_include_directories(SquareRoot
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
- "$<INSTALL_INTERFACE:include>"
+ "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
# install the target and create export-set
install(TARGETS SquareRoot
EXPORT SquareRootTargets
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib
- RUNTIME DESTINATION bin
- INCLUDES DESTINATION include
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
# install header file
-install(FILES SquareRoot.h DESTINATION include)
+install(FILES SquareRoot.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# generate and install export file
install(EXPORT SquareRootTargets
FILE MathFunctionsSquareRootTargets.cmake
NAMESPACE MathFunctions::
- DESTINATION lib/cmake/MathFunctions
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions
)
diff --git a/Help/guide/importing-exporting/index.rst b/Help/guide/importing-exporting/index.rst
index 2e6e06da4..dd3efb8bb 100644
--- a/Help/guide/importing-exporting/index.rst
+++ b/Help/guide/importing-exporting/index.rst
@@ -202,6 +202,10 @@ project. Start by specifying the :command:`cmake_minimum_required` version and
:language: cmake
:end-before: # create library
+The :module:`GNUInstallDirs` module is included in order to provide the
+project with the flexibility to install into different platform layouts by
+making the directories available as cache variables.
+
Create a library called ``MathFunctions`` with the :command:`add_library`
command:
@@ -636,7 +640,7 @@ We can use the :command:`find_package` command:
:start-after: # find MathFunctions
:end-before: # create executable
-Create an exectuable:
+Create an executable:
.. literalinclude:: Downstream/CMakeLists.txt
:language: cmake
diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst
new file mode 100644
index 000000000..41e8479b2
--- /dev/null
+++ b/Help/guide/tutorial/A Basic Starting Point.rst
@@ -0,0 +1,151 @@
+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)
+
+ # set the project name
+ project(Tutorial)
+
+ # add the executable
+ add_executable(Tutorial tutorial.cxx)
+
+
+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.
+
+Adding a Version Number and Configured Header File
+--------------------------------------------------
+
+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.
+
+First, modify the ``CMakeLists.txt`` file to use the :command:`project` command
+to set the project name and version number.
+
+.. literalinclude:: Step2/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-project-VERSION
+ :language: cmake
+ :end-before: # specify the C++ standard
+
+Then, configure a header file to pass the version number to the source
+code:
+
+.. 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
+
+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:
+
+.. literalinclude:: Step2/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-target_include_directories
+ :language: cmake
+ :start-after: # so that we will find TutorialConfig.h
+
+Using your favorite editor, create ``TutorialConfig.h.in`` in the source
+directory with the following contents:
+
+.. literalinclude:: Step2/TutorialConfig.h.in
+ :caption: TutorialConfig.h.in
+ :name: TutorialConfig.h.in
+ :language: c++
+
+When CMake configures this header file the values for
+``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be
+replaced.
+
+Next modify ``tutorial.cxx`` to include the configured header file,
+``TutorialConfig.h``.
+
+Finally, let's print out the executable name and version number by updating
+``tutorial.cxx`` as follows:
+
+.. literalinclude:: Step2/tutorial.cxx
+ :caption: tutorial.cxx
+ :name: tutorial.cxx-print-version
+ :language: c++
+ :start-after: {
+ :end-before: // convert input to double
+
+Specify the C++ Standard
+-------------------------
+
+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>``.
+
+.. literalinclude:: Step2/tutorial.cxx
+ :caption: tutorial.cxx
+ :name: tutorial.cxx-cxx11
+ :language: c++
+ :start-after: // convert input to double
+ :end-before: // calculate square root
+
+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``.
+
+.. literalinclude:: Step2/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-CXX_STANDARD
+ :language: cmake
+ :end-before: # configure a header file to pass some of the CMake settings
+
+Build and Test
+--------------
+
+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.
+
+For example, from the command line we could navigate to the
+``Help/guide/tutorial`` directory of the CMake source code tree and create a
+build directory:
+
+.. code-block:: console
+
+ mkdir Step1_build
+
+Next, navigate to the build directory and run CMake to configure the project
+and generate a native build system:
+
+.. code-block:: console
+
+ cd Step1_build
+ cmake ../Step1
+
+Then call that build system to actually compile/link the project:
+
+.. code-block:: console
+
+ cmake --build .
+
+Finally, try to use the newly built ``Tutorial`` with these commands:
+
+.. code-block:: console
+
+ Tutorial 4294967296
+ Tutorial 10
+ Tutorial
diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst
new file mode 100644
index 000000000..e5ab6a226
--- /dev/null
+++ b/Help/guide/tutorial/Adding Export Configuration.rst
@@ -0,0 +1,100 @@
+Step 11: Adding Export Configuration
+====================================
+
+During :guide:`tutorial/Installing and Testing` of the tutorial we added the
+ability for CMake to install the library and headers of the project. During
+:guide:`tutorial/Packaging an Installer` we added the ability to package up
+this information so it could be distributed to other people.
+
+The next step is to add the necessary information so that other CMake projects
+can use our project, be it from a build directory, a local install or when
+packaged.
+
+The first step is to update our :command:`install(TARGETS)` commands to not
+only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword
+generates and installs a CMake file containing code to import all targets
+listed in the install command from the installation tree. So let's go ahead and
+explicitly ``EXPORT`` the ``MathFunctions`` library by updating the ``install``
+command in ``MathFunctions/CMakeLists.txt`` to look like:
+
+.. literalinclude:: Complete/MathFunctions/CMakeLists.txt
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-install-TARGETS-EXPORT
+ :language: cmake
+ :start-after: # install rules
+
+Now that we have ``MathFunctions`` being exported, we also need to explicitly
+install the generated ``MathFunctionsTargets.cmake`` file. This is done by
+adding the following to the bottom of the top-level ``CMakeLists.txt``:
+
+.. literalinclude:: Complete/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-install-EXPORT
+ :language: cmake
+ :start-after: # install the configuration targets
+ :end-before: include(CMakePackageConfigHelpers)
+
+At this point you should try and run CMake. If everything is setup properly
+you will see that CMake will generate an error that looks like:
+
+.. code-block:: console
+
+ Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
+ path:
+
+ "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
+
+ which is prefixed in the source directory.
+
+What CMake is trying to say is that during generating the export information
+it will export a path that is intrinsically tied to the current machine and
+will not be valid on other machines. The solution to this is to update the
+``MathFunctions`` :command:`target_include_directories` to understand that it
+needs different ``INTERFACE`` locations when being used from within the build
+directory and from an install / package. This means converting the
+:command:`target_include_directories` call for ``MathFunctions`` to look like:
+
+.. literalinclude:: Step12/MathFunctions/CMakeLists.txt
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-target_include_directories
+ :language: cmake
+ :start-after: # to find MathFunctions.h, while we don't.
+ :end-before: # should we use our own math functions
+
+Once this has been updated, we can re-run CMake and verify that it doesn't
+warn anymore.
+
+At this point, we have CMake properly packaging the target information that is
+required but we will still need to generate a ``MathFunctionsConfig.cmake`` so
+that the CMake :command:`find_package` command can find our project. So let's go
+ahead and add a new file to the top-level of the project called
+``Config.cmake.in`` with the following contents:
+
+.. literalinclude:: Step12/Config.cmake.in
+ :caption: Config.cmake.in
+ :name: Config.cmake.in
+
+Then, to properly configure and install that file, add the following to the
+bottom of the top-level ``CMakeLists.txt``:
+
+.. literalinclude:: Step12/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-install-Config.cmake
+ :language: cmake
+ :start-after: # install the configuration targets
+ :end-before: # generate the export
+
+At this point, we have generated a relocatable CMake Configuration for our
+project that can be used after the project has been installed or packaged. If
+we want our project to also be used from a build directory we only have to add
+the following to the bottom of the top level ``CMakeLists.txt``:
+
+.. literalinclude:: Step12/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-export
+ :language: cmake
+ :start-after: # needs to be after the install(TARGETS ) command
+
+With this export call we now generate a ``Targets.cmake``, allowing the
+configured ``MathFunctionsConfig.cmake`` in the build directory to be used by
+other projects, without needing it to be installed.
diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst
new file mode 100644
index 000000000..55acb346f
--- /dev/null
+++ b/Help/guide/tutorial/Adding Generator Expressions.rst
@@ -0,0 +1,74 @@
+Step 10: Adding Generator Expressions
+=====================================
+
+:manual:`Generator expressions <cmake-generator-expressions(7)>` are evaluated
+during build system generation to produce information specific to each build
+configuration.
+
+:manual:`Generator expressions <cmake-generator-expressions(7)>` are allowed in
+the context of many target properties, such as :prop_tgt:`LINK_LIBRARIES`,
+:prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and others.
+They may also be used when using commands to populate those properties, such as
+:command:`target_link_libraries`, :command:`target_include_directories`,
+:command:`target_compile_definitions` and others.
+
+:manual:`Generator expressions <cmake-generator-expressions(7)>` may be used
+to enable conditional linking, conditional definitions used when compiling,
+conditional include directories and more. The conditions may be based on the
+build configuration, target properties, platform information or any other
+queryable information.
+
+There are different types of
+:manual:`generator expressions <cmake-generator-expressions(7)>` including
+Logical, Informational, and Output expressions.
+
+Logical expressions are used to create conditional output. The basic
+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.
+
+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`.
+
+So the following code:
+
+.. literalinclude:: Step10/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-CXX_STANDARD-variable-remove
+ :language: cmake
+ :start-after: project(Tutorial VERSION 1.0)
+ :end-before: # control where the static and shared libraries are built so that on windows
+
+Would be replaced with:
+
+.. literalinclude:: Step11/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-cxx_std-feature
+ :language: cmake
+ :start-after: project(Tutorial VERSION 1.0)
+ :end-before: # add compiler warning flags just when building this project via
+
+
+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:
+
+.. literalinclude:: Step11/CMakeLists.txt
+ :caption: 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
+
+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.
+
+**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have
+a :command:`target_link_libraries` call to ``tutorial_compiler_flags``.
diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
new file mode 100644
index 000000000..26aae4f81
--- /dev/null
+++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
@@ -0,0 +1,61 @@
+Step 8: Adding Support for a Testing Dashboard
+==============================================
+
+Adding support for submitting our test results to a dashboard is simple. We
+already defined a number of tests for our project in
+:ref:`Testing Support <Tutorial Testing Support>`. Now we just have to run
+those tests and submit them to a dashboard. To include support for dashboards
+we include the :module:`CTest` module in our top-level ``CMakeLists.txt``.
+
+Replace:
+
+.. code-block:: cmake
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-enable_testing-remove
+
+ # enable testing
+ enable_testing()
+
+With:
+
+.. code-block:: cmake
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-include-CTest
+
+ # enable dashboard scripting
+ include(CTest)
+
+The :module:`CTest` module will automatically call ``enable_testing()``, so we
+can remove it from our CMake files.
+
+We will also need to create a ``CTestConfig.cmake`` file in the top-level
+directory where we can specify the name of the project and where to submit the
+dashboard.
+
+.. literalinclude:: Step9/CTestConfig.cmake
+ :caption: CTestConfig.cmake
+ :name: CTestConfig.cmake
+ :language: cmake
+
+The :manual:`ctest <ctest(1)>` executable will read in this file when it runs.
+To create a simple dashboard you can run the :manual:`cmake <cmake(1)>`
+executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project,
+but do not build it yet. Instead, change directory to the binary tree, and then
+run:
+
+.. code-block:: console
+
+ ctest [-VV] -D Experimental
+
+Remember, for multi-config generators (e.g. Visual Studio), the configuration
+type must be specified:
+
+.. code-block:: console
+
+ ctest [-VV] -C Debug -D Experimental
+
+Or, from an IDE, build the ``Experimental`` target.
+
+The :manual:`ctest <ctest(1)>` executable will build and test the project and
+submit the results to Kitware's public dashboard:
+https://my.cdash.org/index.php?project=CMakeTutorial.
diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst
new file mode 100644
index 000000000..7210a8dbc
--- /dev/null
+++ b/Help/guide/tutorial/Adding System Introspection.rst
@@ -0,0 +1,58 @@
+Step 5: Adding System Introspection
+===================================
+
+Let us consider adding some code to our project that depends on features the
+target platform may not have. For this example, we will add some code that
+depends on whether or not the target platform has the ``log`` and ``exp``
+functions. Of course almost every platform has these functions but for this
+tutorial assume that they are not common.
+
+If the platform has ``log`` and ``exp`` then we will use them to compute the
+square root in the ``mysqrt`` function. We first test for the availability of
+these functions using the :module:`CheckSymbolExists` module in
+``MathFunctions/CMakeLists.txt``. On some platforms, we will need to link to
+the ``m`` library. If ``log`` and ``exp`` are not initially found, require the
+``m`` library and try again.
+
+.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-check_symbol_exists
+ :language: cmake
+ :start-after: # does this system provide the log and exp functions?
+ :end-before: # add compile definitions
+
+If available, use :command:`target_compile_definitions` to specify
+``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions.
+
+.. literalinclude:: Step6/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
+
+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
+ :caption: MathFunctions/mysqrt.cxx
+ :name: MathFunctions/mysqrt.cxx-ifdef
+ :language: c++
+ :start-after: // if we have both log and exp then use them
+ :end-before: // do ten iterations
+
+We will also need to modify ``mysqrt.cxx`` to include ``cmath``.
+
+.. literalinclude:: Step6/MathFunctions/mysqrt.cxx
+ :caption: MathFunctions/mysqrt.cxx
+ :name: MathFunctions/mysqrt.cxx-include-cmath
+ :language: c++
+ :end-before: #include <iostream>
+
+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 and run the Tutorial executable.
+
+Which function gives better results now, ``sqrt`` or ``mysqrt``?
diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst
new file mode 100644
index 000000000..a8e914eda
--- /dev/null
+++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst
@@ -0,0 +1,52 @@
+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``:
+
+.. literalinclude:: Step4/MathFunctions/CMakeLists.txt
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE
+ :language: cmake
+ :start-after: # to find MathFunctions.h
+
+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:
+
+.. literalinclude:: Step4/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-remove-EXTRA_INCLUDES
+ :language: cmake
+ :start-after: # add the MathFunctions library
+ :end-before: # add the executable
+
+And here:
+
+.. literalinclude:: Step4/CMakeLists.txt
+ :caption: 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.
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
new file mode 100644
index 000000000..70c669562
--- /dev/null
+++ b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst
@@ -0,0 +1,85 @@
+Step 6: Adding a Custom Command and Generated File
+==================================================
+
+Suppose, for the purpose of this tutorial, we decide that we never want to use
+the platform ``log`` and ``exp`` functions and instead would like to
+generate a table of precomputed values to use in the ``mysqrt`` function.
+In this section, we will create the table as part of the build process,
+and then compile that table into our application.
+
+First, let's remove the check for the ``log`` and ``exp`` functions in
+``MathFunctions/CMakeLists.txt``. Then remove the check for ``HAVE_LOG`` and
+``HAVE_EXP`` from ``mysqrt.cxx``. At the same time, we can remove
+:code:`#include <cmath>`.
+
+In the ``MathFunctions`` subdirectory, a new source file named
+``MakeTable.cxx`` has been provided to generate the table.
+
+After reviewing the file, we can see that the table is produced as valid C++
+code and that the output filename is passed in as an argument.
+
+The next step is to add the appropriate commands to the
+``MathFunctions/CMakeLists.txt`` file to build the MakeTable executable and
+then run it as part of the build process. A few commands are needed to
+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
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-add_executable-MakeTable
+ :language: cmake
+ :start-after: # first we add the executable that generates the table
+ :end-before: # add the command to generate the source code
+
+Then we add a custom command that specifies how to produce ``Table.h``
+by running MakeTable.
+
+.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-add_custom_command-Table.h
+ :language: cmake
+ :start-after: # add the command to generate the source code
+ :end-before: # add the main library
+
+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
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-add_library-Table.h
+ :language: cmake
+ :start-after: # add the main library
+ :end-before: # state that anybody linking
+
+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
+ :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
+
+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
+ :caption: MathFunctions/mysqrt.cxx
+ :name: MathFunctions/mysqrt.cxx
+ :language: c++
+ :start-after: // a hack square root calculation using simple operations
+
+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.
+
+When this project is built it will first build the ``MakeTable`` executable.
+It will then run ``MakeTable`` to produce ``Table.h``. Finally, it will
+compile ``mysqrt.cxx`` which includes ``Table.h`` to produce the
+``MathFunctions`` library.
+
+Run the Tutorial executable and verify that it is using the table.
diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst
new file mode 100644
index 000000000..180636141
--- /dev/null
+++ b/Help/guide/tutorial/Adding a Library.rst
@@ -0,0 +1,130 @@
+Step 2: Adding a Library
+========================
+
+Now we will add a library to our project. This library will contain 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.
+
+Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions``
+directory:
+
+.. literalinclude:: Step3/MathFunctions/CMakeLists.txt
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt
+ :language: cmake
+
+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 ``mysqrt.h`` header file can be found. The
+last few lines of the top-level ``CMakeLists.txt`` file should now look like:
+
+.. code-block:: cmake
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-add_subdirectory
+
+ # add the MathFunctions library
+ add_subdirectory(MathFunctions)
+
+ # add the executable
+ add_executable(Tutorial tutorial.cxx)
+
+ target_link_libraries(Tutorial PUBLIC MathFunctions)
+
+ # 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"
+ )
+
+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.
+
+.. literalinclude:: Step3/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-option
+ :language: cmake
+ :start-after: # should we use our own math functions
+ :end-before: # add the MathFunctions library
+
+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 change the end of the top-level ``CMakeLists.txt``
+file to look like the following:
+
+.. literalinclude:: Step3/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS
+ :language: cmake
+ :start-after: # add the MathFunctions library
+
+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.
+
+The corresponding changes to the source code are fairly straightforward.
+First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we
+need it:
+
+.. literalinclude:: Step3/tutorial.cxx
+ :caption: 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
+function is used:
+
+.. literalinclude:: Step3/tutorial.cxx
+ :caption: 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
+
+Since the source code now requires ``USE_MYMATH`` we can add it to
+``TutorialConfig.h.in`` with the following line:
+
+.. literalinclude:: Step3/TutorialConfig.h.in
+ :caption: TutorialConfig.h.in
+ :name: TutorialConfig.h.in-cmakedefine
+ :language: c++
+ :lines: 4
+
+**Exercise**: 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.
+
+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:
+
+.. code-block:: console
+
+ cmake ../Step2 -DUSE_MYMATH=OFF
+
+Rebuild and run the tutorial again.
+
+Which function gives better results, ``sqrt`` or ``mysqrt``?
diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst
new file mode 100644
index 000000000..2fc3202e5
--- /dev/null
+++ b/Help/guide/tutorial/Installing and Testing.rst
@@ -0,0 +1,93 @@
+Step 4: Installing and Testing
+==============================
+
+Now we can start adding install rules and testing support to our project.
+
+Install Rules
+-------------
+
+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.
+
+So to the end of ``MathFunctions/CMakeLists.txt`` we add:
+
+.. literalinclude:: Step5/MathFunctions/CMakeLists.txt
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-install-TARGETS
+ :language: cmake
+ :start-after: # install rules
+
+And to the end of the top-level ``CMakeLists.txt`` we add:
+
+.. literalinclude:: Step5/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-install-TARGETS
+ :language: cmake
+ :start-after: # add the install targets
+ :end-before: # enable testing
+
+That is all that is needed to create a basic local install of the tutorial.
+
+Now 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:
+
+.. code-block:: console
+
+ cmake --install .
+
+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:
+
+.. code-block:: console
+
+ cmake --install . --prefix "/home/myuser/installdir"
+
+Navigate to the install directory and verify that the installed Tutorial runs.
+
+.. _`Tutorial Testing Support`:
+
+Testing Support
+---------------
+
+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.
+
+.. literalinclude:: Step5/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-enable_testing
+ :language: cmake
+ :start-after: # enable testing
+
+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.
+
+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.
+
+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.
+
+Rebuild the application and then cd to the binary directory and run the
+:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For
+multi-config generators (e.g. Visual Studio), the configuration type must be
+specified. To run tests in Debug mode, for example, use ``ctest -C Debug -VV``
+from the build directory (not the Debug subdirectory!). Alternatively, build
+the ``RUN_TESTS`` target from the IDE.
diff --git a/Help/guide/tutorial/Packaging Debug and Release.rst b/Help/guide/tutorial/Packaging Debug and Release.rst
new file mode 100644
index 000000000..91b46a778
--- /dev/null
+++ b/Help/guide/tutorial/Packaging Debug and Release.rst
@@ -0,0 +1,86 @@
+Step 12: Packaging Debug and Release
+====================================
+
+**Note:** This example is valid for single-configuration generators and will
+not work for multi-configuration generators (e.g. Visual Studio).
+
+By default, CMake's model is that a build directory only contains a single
+configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. It is
+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.
+
+Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level
+``CMakeLists.txt`` file:
+
+.. literalinclude:: Complete/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-CMAKE_DEBUG_POSTFIX-variable
+ :language: cmake
+ :start-after: project(Tutorial VERSION 1.0)
+ :end-before: target_compile_features(tutorial_compiler_flags
+
+And the :prop_tgt:`DEBUG_POSTFIX` property on the tutorial executable:
+
+.. literalinclude:: Complete/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-DEBUG_POSTFIX-property
+ :language: cmake
+ :start-after: # add the executable
+ :end-before: # add the binary tree to the search path for include files
+
+Let's also add version numbering to the ``MathFunctions`` library. In
+``MathFunctions/CMakeLists.txt``, set the :prop_tgt:`VERSION` and
+:prop_tgt:`SOVERSION` properties:
+
+.. literalinclude:: Complete/MathFunctions/CMakeLists.txt
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-VERSION-properties
+ :language: cmake
+ :start-after: # setup the version numbering
+ :end-before: # install rules
+
+From the ``Step12`` directory, create ``debug`` and ``release``
+subbdirectories. The layout will look like:
+
+.. code-block:: none
+
+ - Step12
+ - debug
+ - release
+
+Now we need to setup debug and release builds. We can use
+:variable:`CMAKE_BUILD_TYPE` to set the configuration type:
+
+.. code-block:: console
+
+ cd debug
+ cmake -DCMAKE_BUILD_TYPE=Debug ..
+ cmake --build .
+ cd ../release
+ cmake -DCMAKE_BUILD_TYPE=Release ..
+ cmake --build .
+
+Now that both the debug and release builds are complete, we can use a custom
+configuration file to package both builds into a single release. In the
+``Step12`` directory, create a file called ``MultiCPackConfig.cmake``. In this
+file, first include the default configuration file that was created by the
+:manual:`cmake <cmake(1)>` executable.
+
+Next, use the ``CPACK_INSTALL_CMAKE_PROJECTS`` variable to specify which
+projects to install. In this case, we want to install both debug and release.
+
+.. literalinclude:: Complete/MultiCPackConfig.cmake
+ :caption: MultiCPackConfig.cmake
+ :name: MultiCPackConfig.cmake
+ :language: cmake
+
+From the ``Step12`` directory, run :manual:`cpack <cpack(1)>` specifying our
+custom configuration file with the ``config`` option:
+
+.. code-block:: console
+
+ cpack --config MultiCPackConfig.cmake
diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst
new file mode 100644
index 000000000..5eb3e3e5f
--- /dev/null
+++ b/Help/guide/tutorial/Packaging an Installer.rst
@@ -0,0 +1,57 @@
+Step 7: Packaging an Installer
+==============================
+
+Next suppose that we want to distribute our project to other people so that
+they can use it. We want to provide both binary and source distributions on a
+variety of platforms. This is a little different from the install we did
+previously in :guide:`tutorial/Installing and Testing`, where we were
+installing the binaries that we had built from the source code. In this
+example we will be building installation packages that support binary
+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
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-include-CPack
+ :language: cmake
+ :start-after: # setup installer
+
+That is all there is to it. We start by including
+:module:`InstallRequiredSystemLibraries`. This module will include any runtime
+libraries that are needed by the project for the current platform. Next we set
+some CPack variables to where we have stored the license and version
+information for this project. The version information was set earlier in this
+tutorial and the ``license.txt`` has been included in the top-level source
+directory for this step.
+
+Finally we include the :module:`CPack module <CPack>` which will use these
+variables and some other properties of the current system to setup an
+installer.
+
+The next step is to build the project in the usual manner and then run the
+:manual:`cpack <cpack(1)>` executable. To build a binary distribution, from the
+binary directory run:
+
+.. code-block:: console
+
+ cpack
+
+To specify the generator, use the ``-G`` option. For multi-config builds, use
+``-C`` to specify the configuration. For example:
+
+.. code-block:: console
+
+ cpack -G ZIP -C Debug
+
+To create a source distribution you would type:
+
+.. code-block:: console
+
+ cpack --config CPackSourceConfig.cmake
+
+Alternatively, run ``make package`` or right click the ``Package`` target and
+``Build Project`` from an IDE.
+
+Run the installer found in the binary directory. Then run the installed
+executable and verify that it works.
diff --git a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst
new file mode 100644
index 000000000..2d5f70e06
--- /dev/null
+++ b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst
@@ -0,0 +1,77 @@
+Step 9: 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`,
+and allow control over how libraries without an explicit type (``STATIC``,
+``SHARED``, ``MODULE`` or ``OBJECT``) are built.
+
+To accomplish this we need to add :variable:`BUILD_SHARED_LIBS` to the
+top-level ``CMakeLists.txt``. We use the :command:`option` command as it allows
+users to optionally select if the value should be ``ON`` or ``OFF``.
+
+Next we are going to refactor ``MathFunctions`` to become a real library that
+encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling
+code to do this logic. This will also mean that ``USE_MYMATH`` will not control
+building ``MathFunctions``, but instead will control the behavior of this
+library.
+
+The first step is to update the starting section of the top-level
+``CMakeLists.txt`` to look like:
+
+.. literalinclude:: Step10/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-option-BUILD_SHARED_LIBS
+ :language: cmake
+ :end-before: # add the binary tree
+
+Now that we have made ``MathFunctions`` always be used, we will need to update
+the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to
+create a SqrtLibrary that will conditionally be built and installed when
+``USE_MYMATH`` is enabled. Now, since this is a tutorial, we are going to
+explicitly require that SqrtLibrary is built statically.
+
+The end result is that ``MathFunctions/CMakeLists.txt`` should look like:
+
+.. literalinclude:: Step10/MathFunctions/CMakeLists.txt
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-add_library-STATIC
+ :language: cmake
+ :lines: 1-36,42-
+
+Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and
+``detail`` namespaces:
+
+.. literalinclude:: Step10/MathFunctions/mysqrt.cxx
+ :caption: MathFunctions/mysqrt.cxx
+ :name: MathFunctions/mysqrt.cxx-namespace
+ :language: c++
+
+We also need to make some changes in ``tutorial.cxx``, so that it no longer
+uses ``USE_MYMATH``:
+
+#. Always include ``MathFunctions.h``
+#. Always use ``mathfunctions::sqrt``
+#. Don't include ``cmath``
+
+Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines:
+
+.. literalinclude:: Step10/MathFunctions/MathFunctions.h
+ :caption: MathFunctions/MathFunctions.h
+ :name: MathFunctions/MathFunctions.h
+ :language: c++
+
+At this point, if you build everything, you may notice that linking fails
+as we are combining a static library without position independent code with a
+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
+ :caption: MathFunctions/CMakeLists.txt
+ :name: MathFunctions/CMakeLists.txt-POSITION_INDEPENDENT_CODE
+ :language: cmake
+ :lines: 37-42
+
+**Exercise**: We modified ``MathFunctions.h`` to use dll export defines.
+Using CMake documentation can you find a helper module to simplify this?
diff --git a/Help/guide/tutorial/Step12/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt
index eca79d9df..1b0c82667 100644
--- a/Help/guide/tutorial/Step12/CMakeLists.txt
+++ b/Help/guide/tutorial/Step12/CMakeLists.txt
@@ -110,6 +110,7 @@ write_basic_package_version_file(
# install the configuration file
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake
DESTINATION lib/cmake/MathFunctions
)
diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst
index 94753d5dc..8b20a2dfe 100644
--- a/Help/guide/tutorial/index.rst
+++ b/Help/guide/tutorial/index.rst
@@ -1,946 +1,43 @@
CMake Tutorial
**************
-.. only:: html
-
- .. contents::
-
Introduction
============
The CMake tutorial provides a step-by-step guide that covers common build
system issues that CMake helps address. Seeing how various topics all
-work together in an example project can be very helpful. The tutorial
-documentation and source code for examples can be found in the
-``Help/guide/tutorial`` directory of the CMake source code tree. Each step has
-its own subdirectory containing code that may be used as a starting point. The
-tutorial examples are progressive so that each step provides the complete
-solution for the previous step.
-
-A Basic Starting Point (Step 1)
-===============================
-
-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
-
- cmake_minimum_required(VERSION 3.10)
-
- # set the project name
- project(Tutorial)
-
- # add the executable
- add_executable(Tutorial tutorial.cxx)
-
-
-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.
-
-Adding a Version Number and Configured Header File
---------------------------------------------------
-
-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.
-
-First, modify the ``CMakeLists.txt`` file to use the :command:`project` command
-to set the project name and version number.
-
-.. literalinclude:: Step2/CMakeLists.txt
- :language: cmake
- :end-before: # specify the C++ standard
-
-Then, configure a header file to pass the version number to the source
-code:
-
-.. literalinclude:: Step2/CMakeLists.txt
- :language: cmake
- :start-after: # to the source code
- :end-before: # add the executable
-
-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:
-
-.. literalinclude:: Step2/CMakeLists.txt
- :language: cmake
- :start-after: # so that we will find TutorialConfig.h
-
-Using your favorite editor, create ``TutorialConfig.h.in`` in the source
-directory with the following contents:
-
-.. literalinclude:: Step2/TutorialConfig.h.in
- :language: cmake
-
-When CMake configures this header file the values for
-``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be
-replaced.
-
-Next modify ``tutorial.cxx`` to include the configured header file,
-``TutorialConfig.h``.
-
-Finally, let's print out the executable name and version number by updating
-``tutorial.cxx`` as follows:
-
-.. literalinclude:: Step2/tutorial.cxx
- :language: c++
- :start-after: {
- :end-before: // convert input to double
-
-Specify the C++ Standard
--------------------------
-
-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>``.
-
-.. literalinclude:: Step2/tutorial.cxx
- :language: c++
- :start-after: // convert input to double
- :end-before: // calculate square root
-
-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``.
-
-.. literalinclude:: Step2/CMakeLists.txt
- :language: cmake
- :end-before: # configure a header file to pass some of the CMake settings
-
-Build and Test
---------------
-
-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.
-
-For example, from the command line we could navigate to the
-``Help/guide/tutorial`` directory of the CMake source code tree and create a
-build directory:
-
-.. code-block:: console
-
- mkdir Step1_build
-
-Next, navigate to the build directory and run CMake to configure the project
-and generate a native build system:
-
-.. code-block:: console
-
- cd Step1_build
- cmake ../Step1
-
-Then call that build system to actually compile/link the project:
-
-.. code-block:: console
-
- cmake --build .
-
-Finally, try to use the newly built ``Tutorial`` with these commands:
-
-.. code-block:: console
-
- Tutorial 4294967296
- Tutorial 10
- Tutorial
-
-Adding a Library (Step 2)
-=========================
-
-Now we will add a library to our project. This library will contain 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.
-
-Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions``
-directory:
-
-.. literalinclude:: Step3/MathFunctions/CMakeLists.txt
- :language: cmake
-
-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 ``mysqrt.h`` header file can be found. The
-last few lines of the top-level ``CMakeLists.txt`` file should now look like:
-
-.. code-block:: cmake
-
- # add the MathFunctions library
- add_subdirectory(MathFunctions)
-
- # add the executable
- add_executable(Tutorial tutorial.cxx)
-
- target_link_libraries(Tutorial PUBLIC MathFunctions)
-
- # 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"
- )
-
-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.
-
-.. literalinclude:: Step3/CMakeLists.txt
- :language: cmake
- :start-after: # should we use our own math functions
- :end-before: # add the MathFunctions library
-
-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 change the end of the top-level ``CMakeLists.txt``
-file to look like the following:
-
-.. literalinclude:: Step3/CMakeLists.txt
- :language: cmake
- :start-after: # add the MathFunctions library
-
-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.
-
-The corresponding changes to the source code are fairly straightforward.
-First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we
-need it:
-
-.. literalinclude:: Step3/tutorial.cxx
- :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
-function is used:
-
-.. literalinclude:: Step3/tutorial.cxx
- :language: c++
- :start-after: // which square root function should we use?
- :end-before: std::cout << "The square root of
-
-Since the source code now requires ``USE_MYMATH`` we can add it to
-``TutorialConfig.h.in`` with the following line:
-
-.. literalinclude:: Step3/TutorialConfig.h.in
- :language: c
- :lines: 4
-
-**Exercise**: 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.
-
-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:
-
-.. code-block:: console
-
- cmake ../Step2 -DUSE_MYMATH=OFF
-
-Rebuild and run the tutorial again.
-
-Which function gives better results, sqrt or mysqrt?
-
-Adding Usage Requirements for Library (Step 3)
-==============================================
-
-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 `Adding a Library (Step 2)`_ 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``:
-
-.. literalinclude:: Step4/MathFunctions/CMakeLists.txt
- :language: cmake
- :start-after: # to find MathFunctions.h
-
-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:
-
-.. literalinclude:: Step4/CMakeLists.txt
- :language: cmake
- :start-after: # add the MathFunctions library
- :end-before: # add the executable
-
-And here:
-
-.. literalinclude:: Step4/CMakeLists.txt
- :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.
-
-Installing and Testing (Step 4)
-===============================
-
-Now we can start adding install rules and testing support to our project.
-
-Install Rules
--------------
-
-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.
-
-So to the end of ``MathFunctions/CMakeLists.txt`` we add:
-
-.. literalinclude:: Step5/MathFunctions/CMakeLists.txt
- :language: cmake
- :start-after: # install rules
-
-And to the end of the top-level ``CMakeLists.txt`` we add:
-
-.. literalinclude:: Step5/CMakeLists.txt
- :language: cmake
- :start-after: # add the install targets
- :end-before: # enable testing
-
-That is all that is needed to create a basic local install of the tutorial.
-
-Now 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:
-
-.. code-block:: console
-
- cmake --install .
-
-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:
-
-.. code-block:: console
-
- cmake --install . --prefix "/home/myuser/installdir"
-
-Navigate to the install directory and verify that the installed Tutorial runs.
-
-Testing Support
----------------
-
-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.
-
-.. literalinclude:: Step5/CMakeLists.txt
- :language: cmake
- :start-after: # enable testing
-
-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.
-
-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.
-
-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.
-
-Rebuild the application and then cd to the binary directory and run the
-:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For
-multi-config generators (e.g. Visual Studio), the configuration type must be
-specified. To run tests in Debug mode, for example, use ``ctest -C Debug -VV``
-from the build directory (not the Debug subdirectory!). Alternatively, build
-the ``RUN_TESTS`` target from the IDE.
-
-Adding System Introspection (Step 5)
-====================================
-
-Let us consider adding some code to our project that depends on features the
-target platform may not have. For this example, we will add some code that
-depends on whether or not the target platform has the ``log`` and ``exp``
-functions. Of course almost every platform has these functions but for this
-tutorial assume that they are not common.
-
-If the platform has ``log`` and ``exp`` then we will use them to compute the
-square root in the ``mysqrt`` function. We first test for the availability of
-these functions using the :module:`CheckSymbolExists` module in
-``MathFunctions/CMakeLists.txt``. On some platforms, we will need to link to
-the m library. If ``log`` and ``exp`` are not initially found, require the m
-library and try again.
-
-.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
- :language: cmake
- :start-after: # does this system provide the log and exp functions?
- :end-before: # add compile definitions
-
-If available, use :command:`target_compile_definitions` to specify
-``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions.
-
-.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
- :language: cmake
- :start-after: # add compile definitions
- :end-before: # install rules
-
-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
- :language: c++
- :start-after: // if we have both log and exp then use them
- :end-before: // do ten iterations
-
-We will also need to modify ``mysqrt.cxx`` to include ``cmath``.
-
-.. literalinclude:: Step6/MathFunctions/mysqrt.cxx
- :language: c++
- :end-before: #include <iostream>
-
-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 and run the Tutorial executable.
-
-Which function gives better results now, sqrt or mysqrt?
-
-Adding a Custom Command and Generated File (Step 6)
-===================================================
-
-Suppose, for the purpose of this tutorial, we decide that we never want to use
-the platform ``log`` and ``exp`` functions and instead would like to
-generate a table of precomputed values to use in the ``mysqrt`` function.
-In this section, we will create the table as part of the build process,
-and then compile that table into our application.
-
-First, let's remove the check for the ``log`` and ``exp`` functions in
-``MathFunctions/CMakeLists.txt``. Then remove the check for ``HAVE_LOG`` and
-``HAVE_EXP`` from ``mysqrt.cxx``. At the same time, we can remove
-:code:`#include <cmath>`.
-
-In the ``MathFunctions`` subdirectory, a new source file named
-``MakeTable.cxx`` has been provided to generate the table.
-
-After reviewing the file, we can see that the table is produced as valid C++
-code and that the output filename is passed in as an argument.
-
-The next step is to add the appropriate commands to the
-``MathFunctions/CMakeLists.txt`` file to build the MakeTable executable and
-then run it as part of the build process. A few commands are needed to
-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
- :language: cmake
- :start-after: # first we add the executable that generates the table
- :end-before: # add the command to generate the source code
-
-Then we add a custom command that specifies how to produce ``Table.h``
-by running MakeTable.
-
-.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
- :language: cmake
- :start-after: # add the command to generate the source code
- :end-before: # add the main library
-
-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
- :language: cmake
- :start-after: # add the main library
- :end-before: # state that anybody linking
-
-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
- :language: cmake
- :start-after: # state that we depend on our bin
- :end-before: # install rules
-
-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
- :language: c++
- :start-after: // a hack square root calculation using simple operations
-
-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.
-
-When this project is built it will first build the ``MakeTable`` executable.
-It will then run ``MakeTable`` to produce ``Table.h``. Finally, it will
-compile ``mysqrt.cxx`` which includes ``Table.h`` to produce the MathFunctions
-library.
-
-Run the Tutorial executable and verify that it is using the table.
-
-Building an Installer (Step 7)
-==============================
-
-Next suppose that we want to distribute our project to other people so that
-they can use it. We want to provide both binary and source distributions on a
-variety of platforms. This is a little different from the install we did
-previously in `Installing and Testing (Step 4)`_ , where we were
-installing the binaries that we had built from the source code. In this
-example we will be building installation packages that support binary
-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
- :language: cmake
- :start-after: # setup installer
-
-That is all there is to it. We start by including
-:module:`InstallRequiredSystemLibraries`. This module will include any runtime
-libraries that are needed by the project for the current platform. Next we set
-some CPack variables to where we have stored the license and version
-information for this project. The version information was set earlier in this
-tutorial and the ``license.txt`` has been included in the top-level source
-directory for this step.
-
-Finally we include the :module:`CPack module <CPack>` which will use these
-variables and some other properties of the current system to setup an
-installer.
-
-The next step is to build the project in the usual manner and then run the
-:manual:`cpack <cpack(1)>` executable. To build a binary distribution, from the
-binary directory run:
-
-.. code-block:: console
-
- cpack
-
-To specify the generator, use the ``-G`` option. For multi-config builds, use
-``-C`` to specify the configuration. For example:
-
-.. code-block:: console
-
- cpack -G ZIP -C Debug
-
-To create a source distribution you would type:
-
-.. code-block:: console
-
- cpack --config CPackSourceConfig.cmake
-
-Alternatively, run ``make package`` or right click the ``Package`` target and
-``Build Project`` from an IDE.
-
-Run the installer found in the binary directory. Then run the installed
-executable and verify that it works.
-
-Adding Support for a Dashboard (Step 8)
-=======================================
-
-Adding support for submitting our test results to a dashboard is simple. We
-already defined a number of tests for our project in `Testing Support`_. Now we
-just have to run those tests and submit them to a dashboard. To include support
-for dashboards we include the :module:`CTest` module in our top-level
-``CMakeLists.txt``.
-
-Replace:
-
-.. code-block:: cmake
-
- # enable testing
- enable_testing()
-
-With:
-
-.. code-block:: cmake
-
- # enable dashboard scripting
- include(CTest)
-
-The :module:`CTest` module will automatically call ``enable_testing()``, so we
-can remove it from our CMake files.
-
-We will also need to create a ``CTestConfig.cmake`` file in the top-level
-directory where we can specify the name of the project and where to submit the
-dashboard.
-
-.. literalinclude:: Step9/CTestConfig.cmake
- :language: cmake
-
-The :manual:`ctest <ctest(1)>` executable will read in this file when it runs.
-To create a simple dashboard you can run the :manual:`cmake <cmake(1)>`
-executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project,
-but do not build it yet. Instead, change directory to the binary tree, and then
-run:
-
- ctest [-VV] -D Experimental
-
-Remember, for multi-config generators (e.g. Visual Studio), the configuration
-type must be specified::
-
- ctest [-VV] -C Debug -D Experimental
-
-Or, from an IDE, build the ``Experimental`` target.
-
-The :manual:`ctest <ctest(1)>` executable will build and test the project and
-submit the results to Kitware's public dashboard:
-https://my.cdash.org/index.php?project=CMakeTutorial.
-
-Mixing Static and Shared (Step 9)
-=================================
-
-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`,
-and allow control over how libraries without an explicit type (``STATIC``,
-``SHARED``, ``MODULE`` or ``OBJECT``) are built.
-
-To accomplish this we need to add :variable:`BUILD_SHARED_LIBS` to the
-top-level ``CMakeLists.txt``. We use the :command:`option` command as it allows
-users to optionally select if the value should be ON or OFF.
-
-Next we are going to refactor MathFunctions to become a real library that
-encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling
-code to do this logic. This will also mean that ``USE_MYMATH`` will not control
-building MathFunctions, but instead will control the behavior of this library.
-
-The first step is to update the starting section of the top-level
-``CMakeLists.txt`` to look like:
-
-.. literalinclude:: Step10/CMakeLists.txt
- :language: cmake
- :end-before: # add the binary tree
-
-Now that we have made MathFunctions always be used, we will need to update
-the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to
-create a SqrtLibrary that will conditionally be built and installed when
-``USE_MYMATH`` is enabled. Now, since this is a tutorial, we are going to
-explicitly require that SqrtLibrary is built statically.
-
-The end result is that ``MathFunctions/CMakeLists.txt`` should look like:
-
-.. literalinclude:: Step10/MathFunctions/CMakeLists.txt
- :language: cmake
- :lines: 1-36,42-
-
-Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and
-``detail`` namespaces:
-
-.. literalinclude:: Step10/MathFunctions/mysqrt.cxx
- :language: c++
-
-We also need to make some changes in ``tutorial.cxx``, so that it no longer
-uses ``USE_MYMATH``:
-
-#. Always include ``MathFunctions.h``
-#. Always use ``mathfunctions::sqrt``
-#. Don't include cmath
-
-Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines:
-
-.. literalinclude:: Step10/MathFunctions/MathFunctions.h
- :language: c++
-
-At this point, if you build everything, you may notice that linking fails
-as we are combining a static library without position independent code with a
-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
- :language: cmake
- :lines: 37-42
-
-**Exercise**: We modified ``MathFunctions.h`` to use dll export defines.
-Using CMake documentation can you find a helper module to simplify this?
-
-
-Adding Generator Expressions (Step 10)
-======================================
-
-:manual:`Generator expressions <cmake-generator-expressions(7)>` are evaluated
-during build system generation to produce information specific to each build
-configuration.
-
-:manual:`Generator expressions <cmake-generator-expressions(7)>` are allowed in
-the context of many target properties, such as :prop_tgt:`LINK_LIBRARIES`,
-:prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and others.
-They may also be used when using commands to populate those properties, such as
-:command:`target_link_libraries`, :command:`target_include_directories`,
-:command:`target_compile_definitions` and others.
-
-:manual:`Generator expressions <cmake-generator-expressions(7)>` may be used
-to enable conditional linking, conditional definitions used when compiling,
-conditional include directories and more. The conditions may be based on the
-build configuration, target properties, platform information or any other
-queryable information.
-
-There are different types of
-:manual:`generator expressions <cmake-generator-expressions(7)>` including
-Logical, Informational, and Output expressions.
-
-Logical expressions are used to create conditional output. The basic
-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.
-
-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`.
-
-So the following code:
-
-.. literalinclude:: Step10/CMakeLists.txt
- :language: cmake
- :start-after: project(Tutorial VERSION 1.0)
- :end-before: # control where the static and shared libraries are built so that on windows
-
-Would be replaced with:
-
-.. literalinclude:: Step11/CMakeLists.txt
- :language: cmake
- :start-after: project(Tutorial VERSION 1.0)
- :end-before: # add compiler warning flags just when building this project via
-
-
-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:
-
-.. literalinclude:: Step11/CMakeLists.txt
- :language: cmake
- :start-after: # the BUILD_INTERFACE genex
- :end-before: # control where the static and shared libraries are built so that on windows
-
-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.
-
-
-**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have
-a :command:`target_link_libraries` call to ``tutorial_compiler_flags``.
-
-
-Adding Export Configuration (Step 11)
-=====================================
-
-During `Installing and Testing (Step 4)`_ of the tutorial we added the ability
-for CMake to install the library and headers of the project. During
-`Building an Installer (Step 7)`_ we added the ability to package up this
-information so it could be distributed to other people.
-
-The next step is to add the necessary information so that other CMake projects
-can use our project, be it from a build directory, a local install or when
-packaged.
-
-The first step is to update our :command:`install(TARGETS)` commands to not
-only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword
-generates and installs a CMake file containing code to import all targets
-listed in the install command from the installation tree. So let's go ahead and
-explicitly ``EXPORT`` the MathFunctions library by updating the ``install``
-command in ``MathFunctions/CMakeLists.txt`` to look like:
-
-.. literalinclude:: Complete/MathFunctions/CMakeLists.txt
- :language: cmake
- :start-after: # install rules
-
-Now that we have MathFunctions being exported, we also need to explicitly
-install the generated ``MathFunctionsTargets.cmake`` file. This is done by
-adding the following to the bottom of the top-level ``CMakeLists.txt``:
-
-.. literalinclude:: Complete/CMakeLists.txt
- :language: cmake
- :start-after: # install the configuration targets
- :end-before: include(CMakePackageConfigHelpers)
-
-At this point you should try and run CMake. If everything is setup properly
-you will see that CMake will generate an error that looks like:
-
-.. code-block:: console
-
- Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
- path:
-
- "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
-
- which is prefixed in the source directory.
-
-What CMake is trying to say is that during generating the export information
-it will export a path that is intrinsically tied to the current machine and
-will not be valid on other machines. The solution to this is to update the
-MathFunctions :command:`target_include_directories` to understand that it needs
-different ``INTERFACE`` locations when being used from within the build
-directory and from an install / package. This means converting the
-:command:`target_include_directories` call for MathFunctions to look like:
-
-.. literalinclude:: Step12/MathFunctions/CMakeLists.txt
- :language: cmake
- :start-after: # to find MathFunctions.h, while we don't.
- :end-before: # should we use our own math functions
-
-Once this has been updated, we can re-run CMake and verify that it doesn't
-warn anymore.
-
-At this point, we have CMake properly packaging the target information that is
-required but we will still need to generate a ``MathFunctionsConfig.cmake`` so
-that the CMake :command:`find_package` command can find our project. So let's go
-ahead and add a new file to the top-level of the project called
-``Config.cmake.in`` with the following contents:
-
-.. literalinclude:: Step12/Config.cmake.in
-
-Then, to properly configure and install that file, add the following to the
-bottom of the top-level ``CMakeLists.txt``:
-
-.. literalinclude:: Step12/CMakeLists.txt
- :language: cmake
- :start-after: # install the configuration targets
- :end-before: # generate the export
-
-At this point, we have generated a relocatable CMake Configuration for our
-project that can be used after the project has been installed or packaged. If
-we want our project to also be used from a build directory we only have to add
-the following to the bottom of the top level ``CMakeLists.txt``:
-
-.. literalinclude:: Step12/CMakeLists.txt
- :language: cmake
- :start-after: # needs to be after the install(TARGETS ) command
-
-With this export call we now generate a ``Targets.cmake``, allowing the
-configured ``MathFunctionsConfig.cmake`` in the build directory to be used by
-other projects, without needing it to be installed.
-
-Packaging Debug and Release (Step 12)
-=====================================
-
-**Note:** This example is valid for single-configuration generators and will
-not work for multi-configuration generators (e.g. Visual Studio).
-
-By default, CMake's model is that a build directory only contains a single
-configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. It is
-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.
-
-Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level
-``CMakeLists.txt`` file:
-
-.. literalinclude:: Complete/CMakeLists.txt
- :language: cmake
- :start-after: project(Tutorial VERSION 1.0)
- :end-before: target_compile_features(tutorial_compiler_flags
-
-And the :prop_tgt:`DEBUG_POSTFIX` property on the tutorial executable:
-
-.. literalinclude:: Complete/CMakeLists.txt
- :language: cmake
- :start-after: # add the executable
- :end-before: # add the binary tree to the search path for include files
-
-Let's also add version numbering to the MathFunctions library. In
-``MathFunctions/CMakeLists.txt``, set the :prop_tgt:`VERSION` and
-:prop_tgt:`SOVERSION` properties:
-
-.. literalinclude:: Complete/MathFunctions/CMakeLists.txt
- :language: cmake
- :start-after: # setup the version numbering
- :end-before: # install rules
-
-From the ``Step12`` directory, create ``debug`` and ``release``
-subbdirectories. The layout will look like:
-
-.. code-block:: none
-
- - Step12
- - debug
- - release
-
-Now we need to setup debug and release builds. We can use
-:variable:`CMAKE_BUILD_TYPE` to set the configuration type:
-
-.. code-block:: console
-
- cd debug
- cmake -DCMAKE_BUILD_TYPE=Debug ..
- cmake --build .
- cd ../release
- cmake -DCMAKE_BUILD_TYPE=Release ..
- cmake --build .
-
-Now that both the debug and release builds are complete, we can use a custom
-configuration file to package both builds into a single release. In the
-``Step12`` directory, create a file called ``MultiCPackConfig.cmake``. In this
-file, first include the default configuration file that was created by the
-:manual:`cmake <cmake(1)>` executable.
-
-Next, use the ``CPACK_INSTALL_CMAKE_PROJECTS`` variable to specify which
-projects to install. In this case, we want to install both debug and release.
-
-.. literalinclude:: Complete/MultiCPackConfig.cmake
- :language: cmake
-
-From the ``Step12`` directory, run :manual:`cpack <cpack(1)>` specifying our
-custom configuration file with the ``config`` option:
-
-.. code-block:: console
-
- cpack --config MultiCPackConfig.cmake
+work together in an example project can be very helpful.
+
+Steps
+=====
+
+The tutorial documentation and source code for examples can be found in
+the ``Help/guide/tutorial`` directory of the CMake source code tree.
+Each step has its own subdirectory containing code that may be used as a
+starting point. The tutorial examples are progressive so that each step
+provides the complete solution for the previous step.
+
+.. toctree::
+ :maxdepth: 2
+
+ A Basic Starting Point
+ Adding a Library
+ Adding Usage Requirements for a Library
+ Installing and Testing
+ 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
+
+..
+ Whenever a step above is renamed or removed, leave forwarding text in
+ its original document file, and list it below to preserve old links
+ to cmake.org/cmake/help/latest/ URLs.
+
+.. toctree::
+ :maxdepth: 1
+ :hidden:
diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt
index 0947e41cb..8e23b7711 100644
--- a/Help/manual/OPTIONS_BUILD.txt
+++ b/Help/manual/OPTIONS_BUILD.txt
@@ -76,6 +76,14 @@
native build system to choose a compiler or SDK. See the
:variable:`CMAKE_GENERATOR_PLATFORM` variable for details.
+``--toolchain <path-to-file>``
+ Specify the cross compiling toolchain file, equivalent to setting
+ :variable:`CMAKE_TOOLCHAIN_FILE` variable.
+
+``--install-prefix <directory>``
+ Specify the installation directory, used by the
+ :variable:`CMAKE_INSTALL_PREFIX` variable. Must be an absolute path.
+
``-Wno-dev``
Suppress developer warnings.
diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst
index 2c2b04cbe..2b0de1101 100644
--- a/Help/manual/cmake-compile-features.7.rst
+++ b/Help/manual/cmake-compile-features.7.rst
@@ -261,6 +261,7 @@ following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
versions specified for each:
* ``Cray``: Cray Compiler Environment version 8.1+.
+* ``Fujitsu``: Fujitsu HPC compiler 4.0+.
* ``PGI``: PGI version 12.10+.
* ``NVHPC``: NVIDIA HPC compilers version 11.0+.
* ``TI``: Texas Instruments compiler.
diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst
index af9a8ab0d..fe146de0f 100644
--- a/Help/manual/cmake-developer.7.rst
+++ b/Help/manual/cmake-developer.7.rst
@@ -350,6 +350,24 @@ look.
PATHS ${PC_Foo_LIBRARY_DIRS}
)
+Alternatively, if the library is available with multiple configurations, you can
+use :module:`SelectLibraryConfigurations` to automatically set the
+``Foo_LIBRARY`` variable instead:
+
+.. code-block:: cmake
+
+ find_library(Foo_LIBRARY_RELEASE
+ NAMES foo
+ PATHS ${PC_Foo_LIBRARY_DIRS}/Release
+ )
+ find_library(Foo_LIBRARY_DEBUG
+ NAMES foo
+ PATHS ${PC_Foo_LIBRARY_DIRS}/Debug
+ )
+
+ include(SelectLibraryConfigurations)
+ select_library_configurations(Foo)
+
If you have a good way of getting the version (from a header file, for
example), you can use that information to set ``Foo_VERSION`` (although
note that find modules have traditionally used ``Foo_VERSION_STRING``,
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index bc1fa1d85..fa38588a8 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -37,9 +37,11 @@ Environment Variables that Control the Build
/envvar/CMAKE_GENERATOR_PLATFORM
/envvar/CMAKE_GENERATOR_TOOLSET
/envvar/CMAKE_LANG_COMPILER_LAUNCHER
+ /envvar/CMAKE_LANG_LINKER_LAUNCHER
/envvar/CMAKE_MSVCIDE_RUN_PATH
/envvar/CMAKE_NO_VERBOSE
/envvar/CMAKE_OSX_ARCHITECTURES
+ /envvar/CMAKE_TOOLCHAIN_FILE
/envvar/DESTDIR
/envvar/LDFLAGS
/envvar/MACOSX_DEPLOYMENT_TARGET
@@ -65,6 +67,8 @@ Environment Variables for Languages
/envvar/CXXFLAGS
/envvar/FC
/envvar/FFLAGS
+ /envvar/HIPCXX
+ /envvar/HIPFLAGS
/envvar/ISPC
/envvar/ISPCFLAGS
/envvar/OBJC
diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst
index 89739b7d5..5e22ea905 100644
--- a/Help/manual/cmake-file-api.7.rst
+++ b/Help/manual/cmake-file-api.7.rst
@@ -443,7 +443,8 @@ Version 1 does not exist to avoid confusion with that from
"hasInstallRule": true,
"minimumCMakeVersion": {
"string": "3.14"
- }
+ },
+ "jsonFile": "<file>"
},
{
"source": "sub",
@@ -453,7 +454,8 @@ Version 1 does not exist to avoid confusion with that from
"targetIndexes": [ 1 ],
"minimumCMakeVersion": {
"string": "3.14"
- }
+ },
+ "jsonFile": "<file>"
}
],
"projects": [
@@ -569,6 +571,13 @@ The members specific to ``codemodel`` objects are:
:command:`install` rules, i.e. whether a ``make install``
or equivalent rule is available.
+ ``jsonFile``
+ A JSON string specifying a path relative to the codemodel file
+ to another JSON file containing a
+ `"codemodel" version 2 "directory" object`_.
+
+ This field was added in codemodel version 2.3.
+
``projects``
A JSON array of entries corresponding to the top-level project
and sub-projects defined in the build system. Each (sub-)project
@@ -633,6 +642,216 @@ The members specific to ``codemodel`` objects are:
to another JSON file containing a
`"codemodel" version 2 "target" object`_.
+"codemodel" version 2 "directory" object
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A codemodel "directory" object is referenced by a `"codemodel" version 2`_
+object's ``directories`` array. Each "directory" object is a JSON object
+with members:
+
+``paths``
+ A JSON object containing members:
+
+ ``source``
+ A string specifying the path to the source directory, represented
+ with forward slashes. If the directory is inside the top-level
+ source directory then the path is specified relative to that
+ directory (with ``.`` for the top-level source directory itself).
+ Otherwise the path is absolute.
+
+ ``build``
+ A string specifying the path to the build directory, represented
+ with forward slashes. If the directory is inside the top-level
+ build directory then the path is specified relative to that
+ directory (with ``.`` for the top-level build directory itself).
+ Otherwise the path is absolute.
+
+``installers``
+ A JSON array of entries corresponding to :command:`install` rules.
+ Each entry is a JSON object containing members:
+
+ ``component``
+ A string specifying the component selected by the corresponding
+ :command:`install` command invocation.
+
+ ``destination``
+ Optional member that is present for specific ``type`` values below.
+ The value is a string specifying the install destination path.
+ The path may be absolute or relative to the install prefix.
+
+ ``paths``
+ Optional member that is present for specific ``type`` values below.
+ The value is a JSON array of entries corresponding to the paths
+ (files or directories) to be installed. Each entry is one of:
+
+ * A string specifying the path from which a file or directory
+ is to be installed. The portion of the path not preceded by
+ a ``/`` also specifies the path (name) to which the file
+ or directory is to be installed under the destination.
+
+ * A JSON object with members:
+
+ ``from``
+ A string specifying the path from which a file or directory
+ is to be installed.
+
+ ``to``
+ A string specifying the path to which the file or directory
+ is to be installed under the destination.
+
+ In both cases the paths are represented with forward slashes. If
+ the "from" path is inside the top-level directory documented by the
+ corresponding ``type`` value, then the path is specified relative
+ to that directory. Otherwise the path is absolute.
+
+ ``type``
+ A string specifying the type of installation rule. The value is one
+ of the following, with some variants providing additional members:
+
+ ``file``
+ An :command:`install(FILES)` or :command:`install(PROGRAMS)` call.
+ The ``destination`` and ``paths`` members are populated, with paths
+ under the top-level *source* directory expressed relative to it.
+ The ``isOptional`` member may exist.
+ This type has no additional members.
+
+ ``directory``
+ An :command:`install(DIRECTORY)` call.
+ The ``destination`` and ``paths`` members are populated, with paths
+ under the top-level *source* directory expressed relative to it.
+ The ``isOptional`` member may exist.
+ This type has no additional members.
+
+ ``target``
+ An :command:`install(TARGETS)` call.
+ The ``destination`` and ``paths`` members are populated, with paths
+ under the top-level *build* directory expressed relative to it.
+ The ``isOptional`` member may exist.
+ This type has additional members ``targetId``, ``targetIndex``,
+ ``targetIsImportLibrary``, and ``targetInstallNamelink``.
+
+ ``export``
+ An :command:`install(EXPORT)` call.
+ The ``destination`` and ``paths`` members are populated, with paths
+ under the top-level *build* directory expressed relative to it.
+ The ``paths`` entries refer to files generated automatically by
+ CMake for installation, and their actual values are considered
+ private implementation details.
+ This type has additional members ``exportName`` and ``exportTargets``.
+
+ ``script``
+ An :command:`install(SCRIPT)` call.
+ This type has additional member ``scriptFile``.
+
+ ``code``
+ An :command:`install(CODE)` call.
+ This type has no additional members.
+
+ ``importedRuntimeArtifacts``
+ An :command:`install(IMPORTED_RUNTIME_ARTIFACTS)` call.
+ The ``destination`` member is populated. The ``isOptional`` member may
+ exist. This type has no additional members.
+
+ ``runtimeDependencySet``
+ An :command:`install(RUNTIME_DEPENDENCY_SET)` call or an
+ :command:`install(TARGETS)` call with ``RUNTIME_DEPENDENCIES``. The
+ ``destination`` member is populated. This type has additional members
+ ``runtimeDependencySetName`` and ``runtimeDependencySetType``.
+
+ ``isExcludeFromAll``
+ Optional member that is present with boolean value ``true`` when
+ :command:`install` is called with the ``EXCLUDE_FROM_ALL`` option.
+
+ ``isForAllComponents``
+ Optional member that is present with boolean value ``true`` when
+ :command:`install(SCRIPT|CODE)` is called with the
+ ``ALL_COMPONENTS`` option.
+
+ ``isOptional``
+ Optional member that is present with boolean value ``true`` when
+ :command:`install` is called with the ``OPTIONAL`` option.
+ This is allowed when ``type`` is ``file``, ``directory``, or ``target``.
+
+ ``targetId``
+ Optional member that is present when ``type`` is ``target``.
+ The value is a string uniquely identifying the target to be installed.
+ This matches the ``id`` member of the target in the main
+ "codemodel" object's ``targets`` array.
+
+ ``targetIndex``
+ Optional member that is present when ``type`` is ``target``.
+ The value is an unsigned integer 0-based index into the main "codemodel"
+ object's ``targets`` array for the target to be installed.
+
+ ``targetIsImportLibrary``
+ Optional member that is present when ``type`` is ``target`` and
+ the installer is for a Windows DLL import library file or for an
+ AIX linker import file. If present, it has boolean value ``true``.
+
+ ``targetInstallNamelink``
+ Optional member that is present when ``type`` is ``target`` and
+ the installer corresponds to a target that may use symbolic links
+ to implement the :prop_tgt:`VERSION` and :prop_tgt:`SOVERSION`
+ target properties.
+ The value is a string indicating how the installer is supposed to
+ handle the symlinks: ``skip`` means the installer should skip the
+ symlinks and install only the real file, and ``only`` means the
+ installer should install only the symlinks and not the real file.
+ In all cases the ``paths`` member lists what it actually installs.
+
+ ``exportName``
+ Optional member that is present when ``type`` is ``export``.
+ The value is a string specifying the name of the export.
+
+ ``exportTargets``
+ Optional member that is present when ``type`` is ``export``.
+ The value is a JSON array of entries corresponding to the targets
+ included in the export. Each entry is a JSON object with members:
+
+ ``id``
+ A string uniquely identifying the target. This matches
+ the ``id`` member of the target in the main "codemodel"
+ object's ``targets`` array.
+
+ ``index``
+ An unsigned integer 0-based index into the main "codemodel"
+ object's ``targets`` array for the target.
+
+ ``runtimeDependencySetName``
+ Optional member that is present when ``type`` is ``runtimeDependencySet``
+ and the installer was created by an
+ :command:`install(RUNTIME_DEPENDENCY_SET)` call. The value is a string
+ specifying the name of the runtime dependency set that was installed.
+
+ ``runtimeDependencySetType``
+ Optional member that is present when ``type`` is ``runtimeDependencySet``.
+ The value is a string with one of the following values:
+
+ ``library``
+ Indicates that this installer installs dependencies that are not macOS
+ frameworks.
+
+ ``framework``
+ Indicates that this installer installs dependencies that are macOS
+ frameworks.
+
+ ``scriptFile``
+ Optional member that is present when ``type`` is ``script``.
+ The value is a string specifying the path to the script file on disk,
+ represented with forward slashes. If the file is inside the top-level
+ source directory then the path is specified relative to that directory.
+ Otherwise the path is absolute.
+
+ ``backtrace``
+ Optional member that is present when a CMake language backtrace to
+ the :command:`install` or other command invocation that added this
+ installer is available. The value is an unsigned integer 0-based
+ index into the ``backtraceGraph`` member's ``nodes`` array.
+
+``backtraceGraph``
+ A `"codemodel" version 2 "backtrace graph"`_ whose nodes are referenced
+ from ``backtrace`` members elsewhere in this "directory" object.
+
"codemodel" version 2 "target" object
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -964,40 +1183,48 @@ with members:
with forward slashes.
``backtraceGraph``
- A JSON object describing the graph of backtraces whose nodes are
- referenced from ``backtrace`` members elsewhere. The members are:
+ A `"codemodel" version 2 "backtrace graph"`_ whose nodes are referenced
+ from ``backtrace`` members elsewhere in this "target" object.
- ``nodes``
- A JSON array listing nodes in the backtrace graph. Each entry
- is a JSON object with members:
+"codemodel" version 2 "backtrace graph"
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ``file``
- An unsigned integer 0-based index into the backtrace ``files`` array.
+The ``backtraceGraph`` member of a `"codemodel" version 2 "directory" object`_,
+or `"codemodel" version 2 "target" object`_ is a JSON object describing a
+graph of backtraces. Its nodes are referenced from ``backtrace`` members
+elsewhere in the containing object. The backtrace graph object members are:
- ``line``
- An optional member present when the node represents a line within
- the file. The value is an unsigned integer 1-based line number.
+``nodes``
+ A JSON array listing nodes in the backtrace graph. Each entry
+ is a JSON object with members:
- ``command``
- An optional member present when the node represents a command
- invocation within the file. The value is an unsigned integer
- 0-based index into the backtrace ``commands`` array.
+ ``file``
+ An unsigned integer 0-based index into the backtrace ``files`` array.
- ``parent``
- An optional member present when the node is not the bottom of
- the call stack. The value is an unsigned integer 0-based index
- of another entry in the backtrace ``nodes`` array.
+ ``line``
+ An optional member present when the node represents a line within
+ the file. The value is an unsigned integer 1-based line number.
- ``commands``
- A JSON array listing command names referenced by backtrace nodes.
- Each entry is a string specifying a command name.
+ ``command``
+ An optional member present when the node represents a command
+ invocation within the file. The value is an unsigned integer
+ 0-based index into the backtrace ``commands`` array.
- ``files``
- A JSON array listing CMake language files referenced by backtrace nodes.
- Each entry is a string specifying the path to a file, represented
- with forward slashes. If the file is inside the top-level source
- directory then the path is specified relative to that directory.
- Otherwise the path is absolute.
+ ``parent``
+ An optional member present when the node is not the bottom of
+ the call stack. The value is an unsigned integer 0-based index
+ of another entry in the backtrace ``nodes`` array.
+
+``commands``
+ A JSON array listing command names referenced by backtrace nodes.
+ Each entry is a string specifying a command name.
+
+``files``
+ A JSON array listing CMake language files referenced by backtrace nodes.
+ Each entry is a string specifying the path to a file, represented
+ with forward slashes. If the file is inside the top-level source
+ directory then the path is specified relative to that directory.
+ Otherwise the path is absolute.
Object Kind "cache"
-------------------
@@ -1244,7 +1471,7 @@ The members specific to ``toolchains`` objects are:
``language``
A JSON string specifying the toolchain language, like C or CXX. Language
- names are the same as langauge names that can be passed to the
+ names are the same as language names that can be passed to the
:command:`project` command. Because CMake only supports a single toolchain
per language, this field can be used as a key.
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 7bc490f70..5d508cb0d 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -94,6 +94,8 @@ String Comparisons
.. genex:: $<IN_LIST:string,list>
+ .. versionadded:: 3.12
+
``1`` if ``string`` is member of the semicolon-separated ``list``, else ``0``.
Uses case-sensitive comparisons.
@@ -111,10 +113,14 @@ String Comparisons
.. genex:: $<VERSION_LESS_EQUAL:v1,v2>
+ .. versionadded:: 3.7
+
``1`` if ``v1`` is a version less than or equal to ``v2``, else ``0``.
.. genex:: $<VERSION_GREATER_EQUAL:v1,v2>
+ .. versionadded:: 3.7
+
``1`` if ``v1`` is a version greater than or equal to ``v2``, else ``0``.
Variable Queries
@@ -122,6 +128,8 @@ Variable Queries
.. genex:: $<TARGET_EXISTS:target>
+ .. versionadded:: 3.12
+
``1`` if ``target`` exists, else ``0``.
.. genex:: $<CONFIG:cfgs>
@@ -155,6 +163,8 @@ Variable Queries
.. genex:: $<CUDA_COMPILER_ID:compiler_ids>
+ .. versionadded:: 3.15
+
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the CUDA compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
@@ -162,6 +172,8 @@ Variable Queries
.. genex:: $<OBJC_COMPILER_ID:compiler_ids>
+ .. versionadded:: 3.16
+
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the Objective-C compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
@@ -169,6 +181,8 @@ Variable Queries
.. genex:: $<OBJCXX_COMPILER_ID:compiler_ids>
+ .. versionadded:: 3.16
+
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the Objective-C++ compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
@@ -181,8 +195,17 @@ Variable Queries
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+.. genex:: $<HIP_COMPILER_ID:compiler_ids>
+
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if the CMake's compiler id of the HIP compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+
.. genex:: $<ISPC_COMPILER_ID:compiler_ids>
+ .. versionadded:: 3.19
+
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the ISPC compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
@@ -200,16 +223,22 @@ Variable Queries
.. genex:: $<CUDA_COMPILER_VERSION:version>
+ .. versionadded:: 3.15
+
``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
.. genex:: $<OBJC_COMPILER_VERSION:version>
+ .. versionadded:: 3.16
+
``1`` if the version of the OBJC compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
.. genex:: $<OBJCXX_COMPILER_VERSION:version>
+ .. versionadded:: 3.16
+
``1`` if the version of the OBJCXX compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
@@ -218,8 +247,15 @@ Variable Queries
``1`` if the version of the Fortran compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+.. genex:: $<HIP_COMPILER_VERSION:version>
+
+ ``1`` if the version of the HIP compiler matches ``version``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+
.. genex:: $<ISPC_COMPILER_VERSION:version>
+ .. versionadded:: 3.19
+
``1`` if the version of the ISPC compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
@@ -232,6 +268,8 @@ Variable Queries
.. genex:: $<COMPILE_FEATURES:features>
+ .. versionadded:: 3.1
+
where ``features`` is a comma-spearated list.
Evaluates to ``1`` if all of the ``features`` are available for the 'head'
target, and ``0`` otherwise. If this expression is used while evaluating
@@ -245,6 +283,8 @@ Variable Queries
.. genex:: $<COMPILE_LANG_AND_ID:language,compiler_ids>
+ .. versionadded:: 3.15
+
``1`` when the language used for compilation unit matches ``language`` and
the 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
@@ -282,6 +322,8 @@ Variable Queries
.. genex:: $<COMPILE_LANGUAGE:languages>
+ .. 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
@@ -328,6 +370,8 @@ Variable Queries
.. genex:: $<LINK_LANG_AND_ID:language,compiler_ids>
+ .. 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
@@ -368,6 +412,8 @@ Variable Queries
.. genex:: $<LINK_LANGUAGE:languages>
+ .. 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
@@ -431,6 +477,8 @@ Variable Queries
.. genex:: $<DEVICE_LINK:list>
+ .. versionadded:: 3.18
+
Returns the list if it is the device link step, an empty list otherwise.
The device link step is controlled by :prop_tgt:`CUDA_SEPARABLE_COMPILATION`
and :prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties and
@@ -439,6 +487,8 @@ Variable Queries
.. genex:: $<HOST_LINK:list>
+ .. versionadded:: 3.18
+
Returns the list if it is the normal link step, an empty list otherwise.
This expression is mainly useful when a device link step is also involved
(see ``$<DEVICE_LINK:list>`` generator expression). This expression can only
@@ -521,6 +571,8 @@ that must be ``0`` or ``1``.
.. genex:: $<IF:condition,true_string,false_string>
+ .. versionadded:: 3.8
+
Evaluates to ``true_string`` if ``condition`` is ``1``.
Otherwise evaluates to ``false_string``.
@@ -545,10 +597,14 @@ String Transformations
.. genex:: $<REMOVE_DUPLICATES:list>
+ .. versionadded:: 3.15
+
Removes duplicated items in the given ``list``.
.. genex:: $<FILTER:list,INCLUDE|EXCLUDE,regex>
+ .. versionadded:: 3.15
+
Includes or removes items from ``list`` that match the regular expression ``regex``.
.. genex:: $<LOWER_CASE:string>
@@ -561,12 +617,16 @@ String Transformations
.. genex:: $<GENEX_EVAL:expr>
+ .. versionadded:: 3.12
+
Content of ``expr`` evaluated as a generator expression in the current
context. This enables consumption of generator expressions whose
evaluation results itself in generator expressions.
.. genex:: $<TARGET_GENEX_EVAL:tgt,expr>
+ .. versionadded:: 3.12
+
Content of ``expr`` evaluated as a generator expression in the context of
``tgt`` target. This enables consumption of custom target properties that
themselves contain generator expressions.
@@ -635,11 +695,15 @@ Variable Queries
.. genex:: $<OBJC_COMPILER_ID>
+ .. versionadded:: 3.16
+
The CMake's compiler id of the OBJC compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
.. genex:: $<OBJCXX_COMPILER_ID>
+ .. versionadded:: 3.16
+
The CMake's compiler id of the OBJCXX compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
@@ -648,8 +712,15 @@ Variable Queries
The CMake's compiler id of the Fortran compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+.. genex:: $<HIP_COMPILER_ID>
+
+ The CMake's compiler id of the HIP compiler used.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+
.. genex:: $<ISPC_COMPILER_ID>
+ .. versionadded:: 3.19
+
The CMake's compiler id of the ISPC compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
@@ -670,11 +741,15 @@ Variable Queries
.. genex:: $<OBJC_COMPILER_VERSION>
+ .. versionadded:: 3.16
+
The version of the OBJC compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
.. genex:: $<OBJCXX_COMPILER_VERSION>
+ .. versionadded:: 3.16
+
The version of the OBJCXX compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
@@ -683,13 +758,22 @@ Variable Queries
The version of the Fortran compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+.. genex:: $<HIP_COMPILER_VERSION>
+
+ The version of the HIP compiler used.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+
.. genex:: $<ISPC_COMPILER_VERSION>
+ .. versionadded:: 3.19
+
The version of the ISPC compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
.. genex:: $<COMPILE_LANGUAGE>
+ .. versionadded:: 3.3
+
The compile language of source files when evaluating compile options.
See :ref:`the related boolean expression
<Boolean COMPILE_LANGUAGE Generator Expression>`
@@ -698,6 +782,8 @@ Variable Queries
.. genex:: $<LINK_LANGUAGE>
+ .. versionadded:: 3.18
+
The link language of target when evaluating link options.
See :ref:`the related boolean expression
<Boolean LINK_LANGUAGE Generator Expression>` ``$<LINK_LANGUAGE:language>``
@@ -728,6 +814,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_NAME_IF_EXISTS:tgt>
+ .. versionadded:: 3.12
+
The target name ``tgt`` if the target exists, an empty string otherwise.
Note that ``tgt`` is not added as a dependency of the target this
@@ -739,6 +827,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_FILE_BASE_NAME:tgt>
+ .. versionadded:: 3.15
+
Base name of ``tgt``, i.e. ``$<TARGET_FILE_NAME:tgt>`` without prefix and
suffix.
For example, if the ``tgt`` filename is ``libbase.so``, the base name is ``base``.
@@ -758,6 +848,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_FILE_PREFIX:tgt>
+ .. versionadded:: 3.15
+
Prefix of the ``tgt`` filename (such as ``lib``).
See also the :prop_tgt:`PREFIX` target property.
@@ -767,6 +859,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_FILE_SUFFIX:tgt>
+ .. versionadded:: 3.15
+
Suffix of the ``tgt`` filename (extension such as ``.so`` or ``.exe``).
See also the :prop_tgt:`SUFFIX` target property.
@@ -797,6 +891,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_LINKER_FILE_BASE_NAME:tgt>
+ .. versionadded:: 3.15
+
Base name of file used to link the target ``tgt``, i.e.
``$<TARGET_LINKER_FILE_NAME:tgt>`` without prefix and suffix. For example,
if target file name is ``libbase.a``, the base name is ``base``.
@@ -815,6 +911,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_LINKER_FILE_PREFIX:tgt>
+ .. versionadded:: 3.15
+
Prefix of file used to link target ``tgt``.
See also the :prop_tgt:`PREFIX` and :prop_tgt:`IMPORT_PREFIX` target
@@ -825,6 +923,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_LINKER_FILE_SUFFIX:tgt>
+ .. versionadded:: 3.15
+
Suffix of file used to link where ``tgt`` is the name of a target.
The suffix corresponds to the file extension (such as ".so" or ".lib").
@@ -868,6 +968,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_PDB_FILE:tgt>
+ .. versionadded:: 3.1
+
Full path to the linker generated program database file (.pdb)
where ``tgt`` is the name of a target.
@@ -877,6 +979,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_PDB_FILE_BASE_NAME:tgt>
+ .. versionadded:: 3.15
+
Base name of the linker generated program database file (.pdb)
where ``tgt`` is the name of a target.
@@ -895,6 +999,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_PDB_FILE_NAME:tgt>
+ .. versionadded:: 3.1
+
Name of the linker generated program database file (.pdb).
Note that ``tgt`` is not added as a dependency of the target this
@@ -902,6 +1008,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_PDB_FILE_DIR:tgt>
+ .. versionadded:: 3.1
+
Directory of the linker generated program database file (.pdb).
Note that ``tgt`` is not added as a dependency of the target this
@@ -909,6 +1017,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_BUNDLE_DIR:tgt>
+ .. versionadded:: 3.9
+
Full path to the bundle directory (``my.app``, ``my.framework``, or
``my.bundle``) where ``tgt`` is the name of a target.
@@ -917,6 +1027,8 @@ which is just the string ``tgt``.
.. genex:: $<TARGET_BUNDLE_CONTENT_DIR:tgt>
+ .. versionadded:: 3.9
+
Full path to the bundle content directory where ``tgt`` is the name of a
target. For the macOS SDK it leads to ``my.app/Contents``, ``my.framework``,
or ``my.bundle/Contents``. For all other SDKs (e.g. iOS) it leads to
@@ -940,11 +1052,37 @@ which is just the string ``tgt``.
:ref:`Target Usage Requirements` this is the consuming target rather
than the target specifying the requirement.
+.. genex:: $<TARGET_RUNTIME_DLLS:tgt>
+
+ .. versionadded:: 3.21
+
+ List of DLLs that the target depends on at runtime. This is determined by
+ the locations of all the ``SHARED`` and ``MODULE`` targets in the target's
+ transitive dependencies. Using this generator expression on targets other
+ than executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error.
+ On non-DLL platforms, it evaluates to an empty string.
+
+ This generator expression can be used to copy all of the DLLs that a target
+ depends on into its output directory in a ``POST_BUILD`` custom command. For
+ example:
+
+ .. code-block:: cmake
+
+ find_package(foo REQUIRED)
+
+ add_executable(exe main.c)
+ target_link_libraries(exe PRIVATE foo::foo foo::bar)
+ add_custom_command(TARGET exe POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:exe> $<TARGET_FILE_DIR:exe>
+ COMMAND_EXPAND_LISTS
+ )
+
.. genex:: $<INSTALL_PREFIX>
Content of the install prefix when the target is exported via
- :command:`install(EXPORT)`, or when evaluated in
- :prop_tgt:`INSTALL_NAME_DIR`, and empty otherwise.
+ :command:`install(EXPORT)`, or when evaluated in the
+ :prop_tgt:`INSTALL_NAME_DIR` property or the ``INSTALL_NAME_DIR`` argument of
+ :command:`install(RUNTIME_DEPENDENCY_SET)`, and empty otherwise.
Output-Related Expressions
--------------------------
@@ -957,6 +1095,8 @@ Output-Related Expressions
.. genex:: $<LINK_ONLY:...>
+ .. versionadded:: 3.1
+
Content of ``...`` except when evaluated in a link interface while
propagating :ref:`Target Usage Requirements`, in which case it is the
empty string.
@@ -982,18 +1122,24 @@ Output-Related Expressions
.. genex:: $<TARGET_OBJECTS:objLib>
+ .. versionadded:: 3.1
+
List of objects resulting from build of ``objLib``.
.. genex:: $<SHELL_PATH:...>
+ .. versionadded:: 3.4
+
Content of ``...`` converted to shell path style. For example, slashes are
converted to backslashes in Windows shells and drive letters are converted
to posix paths in MSYS shells. The ``...`` must be an absolute path.
- The ``...`` may be a :ref:`semicolon-separated list <CMake Language Lists>`
- of paths, in which case each path is converted individually and a result
- list is generated using the shell path separator (``:`` on POSIX and
- ``;`` on Windows). Be sure to enclose the argument containing this genex
- in double quotes in CMake source code so that ``;`` does not split arguments.
+
+ .. versionadded:: 3.14
+ The ``...`` may be a :ref:`semicolon-separated list <CMake Language Lists>`
+ of paths, in which case each path is converted individually and a result
+ list is generated using the shell path separator (``:`` on POSIX and
+ ``;`` on Windows). Be sure to enclose the argument containing this genex
+ in double quotes in CMake source code so that ``;`` does not split arguments.
.. genex:: $<OUTPUT_CONFIG:...>
diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst
index 8ca2bf644..663b18d46 100644
--- a/Help/manual/cmake-generators.7.rst
+++ b/Help/manual/cmake-generators.7.rst
@@ -91,6 +91,7 @@ Visual Studio Generators
/generator/Visual Studio 14 2015
/generator/Visual Studio 15 2017
/generator/Visual Studio 16 2019
+ /generator/Visual Studio 17 2022
Other Generators
^^^^^^^^^^^^^^^^
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index 17c1a1e5c..141eeaa76 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -185,6 +185,7 @@ They are normally called through the :command:`find_package` command.
/module/FindMPEG
/module/FindMPEG2
/module/FindMPI
+ /module/FindMsys
/module/FindODBC
/module/FindOpenACC
/module/FindOpenAL
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index bd6b2f0ca..b9e3d452f 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,19 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
to determine whether to report an error on use of deprecated macros or
functions.
+Policies Introduced by CMake 3.21
+=================================
+
+.. toctree::
+ :maxdepth: 1
+
+ CMP0126: set(CACHE) does not remove a normal variable of the same name. </policy/CMP0126>
+ CMP0125: find_(path|file|library|program) have consistent behavior for cache variables. </policy/CMP0125>
+ CMP0124: foreach() loop variables are only available in the loop scope. </policy/CMP0124>
+ CMP0123: ARMClang cpu/arch compile and link flags must be set explicitly. </policy/CMP0123>
+ CMP0122: UseSWIG use standard library name conventions for csharp language. </policy/CMP0122>
+ CMP0121: The list command detects invalid indices. </policy/CMP0121>
+
Policies Introduced by CMake 3.20
=================================
diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst
index 467818dfa..db26b5a40 100644
--- a/Help/manual/cmake-presets.7.rst
+++ b/Help/manual/cmake-presets.7.rst
@@ -39,7 +39,7 @@ The root object recognizes the following fields:
``version``
A required integer representing the version of the JSON schema.
- The supported versions are ``1`` and ``2``.
+ The supported versions are ``1``, ``2``, and ``3``.
``cmakeMinimumRequired``
@@ -70,17 +70,17 @@ The root object recognizes the following fields:
``configurePresets``
An optional array of `Configure Preset`_ objects.
- This is allowed in preset files specifying version 1 or above.
+ 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.
+ 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.
+ This is allowed in preset files specifying version ``2`` or above.
Configure Preset
^^^^^^^^^^^^^^^^
@@ -119,6 +119,11 @@ that may contain the following fields:
This field can also be a string, which is equivalent to an array
containing one string.
+``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
@@ -140,7 +145,9 @@ that may contain the following fields:
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``).
+ ``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
@@ -175,13 +182,29 @@ that may contain the following fields:
ignore the field, but the IDE can use them to set up the environment
before invoking CMake.
+``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,
+ relative to the source directory. Takes precedence over any `CMAKE_TOOLCHAIN_FILE`
+ value. This is allowed in preset files 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
specified, it must be inherited from the ``inherits`` preset (unless this
- preset is ``hidden``).
+ preset is ``hidden``). In version ``3`` or above, this field may be
+ 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``
@@ -338,6 +361,11 @@ that may contain the following fields:
This field can also be a string, which is equivalent to an array
containing one string.
+``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
@@ -373,6 +401,19 @@ that may contain the following fields:
are applied. Setting a variable to ``null`` causes it to not be set,
even if a value was inherited from another preset.
+ .. note::
+
+ For a CMake project using ExternalProject with a configuration preset
+ having environment variables needed in the ExternalProject, use a build
+ preset that inherits that configuration preset or the ExternalProject
+ will not have the environment variables set in the configuration preset.
+ Example: suppose the host defaults to one compiler (say Clang)
+ and the user wishes to use another compiler (say GCC). Set configuration
+ preset environment variables ``CC`` and ``CXX`` and use a build preset
+ that inherits that configuration preset. Otherwise the ExternalProject
+ may use a different (system default) compiler than the top-level CMake
+ project.
+
``configurePreset``
An optional string specifying the name of a configure preset to
@@ -457,6 +498,11 @@ that may contain the following fields:
This field can also be a string, which is equivalent to an array
containing one string.
+``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
@@ -609,7 +655,8 @@ that may contain the following fields:
An optional string specifying a regex for test names. Equivalent to
passing ``--tests-regex`` on the command line. This field supports
- macro expansion.
+ macro expansion. CMake regex syntax is described under
+ :ref:`string(REGEX) <Regex Specification>`.
``label``
@@ -782,6 +829,103 @@ that may contain the following fields:
Equivalent to passing ``--no-tests=ignore`` on the command line.
+Condition
+^^^^^^^^^
+
+The ``condition`` field of a preset, allowed in preset files specifying version
+``3`` or above, is used to determine whether or not the preset is enabled. For
+example, this can be used to disable a preset on platforms other than Windows.
+``condition`` may be either a boolean, ``null``, or an object. If it is a
+boolean, the boolean indicates whether the preset is enabled or disabled. If it
+is ``null``, the preset is enabled, but the ``null`` condition is not inherited
+by any presets that may inherit from the preset. Sub-conditions (for example in
+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
+ 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.
+
+ ``"anyOf"``
+
+ ``"allOf"``
+
+ Indicates that the condition is an aggregation of zero or more nested
+ 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
^^^^^^^^^^^^^^^
@@ -823,6 +967,12 @@ Recognized macros include:
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.
+
``${dollar}``
A literal dollar sign (``$``).
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index af170dabd..5f18a8247 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -21,6 +21,7 @@ Properties of Global Scope
/prop_gbl/AUTOMOC_SOURCE_GROUP
/prop_gbl/AUTOMOC_TARGETS_FOLDER
/prop_gbl/AUTORCC_SOURCE_GROUP
+ /prop_gbl/AUTOUIC_SOURCE_GROUP
/prop_gbl/CMAKE_C_KNOWN_FEATURES
/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES
/prop_gbl/CMAKE_CXX_KNOWN_FEATURES
@@ -73,6 +74,7 @@ Properties on Directories
/prop_dir/DEFINITIONS
/prop_dir/EXCLUDE_FROM_ALL
/prop_dir/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
+ /prop_dir/IMPORTED_TARGETS
/prop_dir/INCLUDE_DIRECTORIES
/prop_dir/INCLUDE_REGULAR_EXPRESSION
/prop_dir/INTERPROCEDURAL_OPTIMIZATION
@@ -211,6 +213,7 @@ Properties on Targets
/prop_tgt/GHS_NO_SOURCE_GROUP_FILE
/prop_tgt/GNUtoMS
/prop_tgt/HAS_CXX
+ /prop_tgt/HIP_ARCHITECTURES
/prop_tgt/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
/prop_tgt/IMPORTED
/prop_tgt/IMPORTED_COMMON_LANGUAGE_RUNTIME
@@ -271,6 +274,7 @@ Properties on Targets
/prop_tgt/LANG_CPPCHECK
/prop_tgt/LANG_CPPLINT
/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE
+ /prop_tgt/LANG_LINKER_LAUNCHER
/prop_tgt/LANG_VISIBILITY_PRESET
/prop_tgt/LIBRARY_OUTPUT_DIRECTORY
/prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG
@@ -402,7 +406,9 @@ Properties on Targets
/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY
/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY
/prop_tgt/XCODE_EMBED_type
+ /prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY
/prop_tgt/XCODE_EMBED_type_PATH
+ /prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY
/prop_tgt/XCODE_EXPLICIT_FILE_TYPE
/prop_tgt/XCODE_GENERATE_SCHEME
/prop_tgt/XCODE_LINK_BUILD_PHASE_MODE
diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst
index 1ededee18..a94131049 100644
--- a/Help/manual/cmake-toolchains.7.rst
+++ b/Help/manual/cmake-toolchains.7.rst
@@ -96,8 +96,8 @@ Cross Compiling
===============
If :manual:`cmake(1)` is invoked with the command line parameter
-``-DCMAKE_TOOLCHAIN_FILE=path/to/file``, the file will be loaded early to set
-values for the compilers.
+``--toolchain path/to/file`` or ``-DCMAKE_TOOLCHAIN_FILE=path/to/file``, 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.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 4317dd407..39fbbed39 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -130,6 +130,7 @@ Variables that Provide Information
/variable/PROJECT-NAME_BINARY_DIR
/variable/PROJECT-NAME_DESCRIPTION
/variable/PROJECT-NAME_HOMEPAGE_URL
+ /variable/PROJECT-NAME_IS_TOP_LEVEL
/variable/PROJECT-NAME_SOURCE_DIR
/variable/PROJECT-NAME_VERSION
/variable/PROJECT-NAME_VERSION_MAJOR
@@ -139,6 +140,7 @@ Variables that Provide Information
/variable/PROJECT_BINARY_DIR
/variable/PROJECT_DESCRIPTION
/variable/PROJECT_HOMEPAGE_URL
+ /variable/PROJECT_IS_TOP_LEVEL
/variable/PROJECT_NAME
/variable/PROJECT_SOURCE_DIR
/variable/PROJECT_VERSION
@@ -243,6 +245,7 @@ Variables that Change Behavior
/variable/CMAKE_SYSTEM_LIBRARY_PATH
/variable/CMAKE_SYSTEM_PREFIX_PATH
/variable/CMAKE_SYSTEM_PROGRAM_PATH
+ /variable/CMAKE_TLS_VERIFY
/variable/CMAKE_USER_MAKE_RULES_OVERRIDE
/variable/CMAKE_WARN_DEPRECATED
/variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
@@ -421,6 +424,7 @@ Variables that Control the Build
/variable/CMAKE_LANG_CPPCHECK
/variable/CMAKE_LANG_CPPLINT
/variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE
+ /variable/CMAKE_LANG_LINKER_LAUNCHER
/variable/CMAKE_LANG_LINK_LIBRARY_FILE_FLAG
/variable/CMAKE_LANG_LINK_LIBRARY_FLAG
/variable/CMAKE_LANG_VISIBILITY_PRESET
@@ -519,6 +523,7 @@ Variables for Languages
/variable/CMAKE_Fortran_MODDIR_DEFAULT
/variable/CMAKE_Fortran_MODDIR_FLAG
/variable/CMAKE_Fortran_MODOUT_FLAG
+ /variable/CMAKE_HIP_ARCHITECTURES
/variable/CMAKE_ISPC_HEADER_DIRECTORY
/variable/CMAKE_ISPC_HEADER_SUFFIX
/variable/CMAKE_ISPC_INSTRUCTION_SETS
@@ -644,6 +649,7 @@ Variables for CTest
/variable/CTEST_RESOURCE_SPEC_FILE
/variable/CTEST_RUN_CURRENT_SCRIPT
/variable/CTEST_SCP_COMMAND
+ /variable/CTEST_SCRIPT_DIRECTORY
/variable/CTEST_SITE
/variable/CTEST_SUBMIT_URL
/variable/CTEST_SOURCE_DIRECTORY
@@ -667,6 +673,7 @@ Variables for CPack
/variable/CPACK_ABSOLUTE_DESTINATION_FILES
/variable/CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY
+ /variable/CPACK_CUSTOM_INSTALL_VARIABLES
/variable/CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
/variable/CPACK_INCLUDE_TOPLEVEL_DIRECTORY
/variable/CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 02828ac5b..e23ddd823 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -381,9 +381,9 @@ Options
``--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 specifies the
- generator and the build directory, and optionally a list of variables and
- other arguments to pass to CMake. The current working directory must contain
+ ``<path-to-source>/CMakeUserPresets.json``. The preset may specify the
+ generator and the build directory, and a list of variables and other
+ arguments to pass to CMake. The current working directory must contain
CMake preset files. The :manual:`CMake GUI <cmake-gui(1)>` can
also recognize ``CMakePresets.json`` and ``CMakeUserPresets.json`` files. For
full details on these files, see :manual:`cmake-presets(7)`.
@@ -408,7 +408,8 @@ project binary tree:
.. code-block:: shell
- cmake --build [<dir> | --preset <preset>] [<options>] [-- <build-tool-options>]
+ cmake --build <dir> [<options>] [-- <build-tool-options>]
+ cmake --build --preset <preset> [<options>] [-- <build-tool-options>]
This abstracts a native build tool's command-line interface with the
following options:
@@ -575,6 +576,12 @@ Available commands are:
``true`` if the generator supports toolsets and ``false`` otherwise.
``platformSupport``
``true`` if the generator supports platforms and ``false`` otherwise.
+ ``supportedPlatforms``
+ .. versionadded:: 3.21
+
+ 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.
``extraGenerators``
A list of strings with all the extra generators compatible with
the generator.
@@ -702,7 +709,7 @@ Available commands are:
``remove [-f] <file>...``
.. deprecated:: 3.17
- Remove the file(s). The planned behaviour was that if any of the
+ Remove the file(s). The planned behavior was that if any of the
listed files already do not exist, the command returns a non-zero exit code,
but no message is logged. The ``-f`` option changes the behavior to return a
zero exit code (i.e. success) in such situations instead.
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index 175359d6c..ab819f94e 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -134,6 +134,12 @@ Options
This option tells CTest to write all its output to a ``<file>`` log file.
+``--output-junit <file>``
+ Write test results in JUnit format.
+
+ This option tells CTest to write test results to a ``<file>`` JUnit XML file.
+ If ``<file>`` already exists it will be overwritten.
+
``-N,--show-only[=<format>]``
Disable actual execution of tests.
@@ -152,10 +158,14 @@ Options
See `Show as JSON Object Model`_.
``-L <regex>, --label-regex <regex>``
- Run tests with labels matching regular expression.
+ Run tests with labels matching regular expression as described under
+ :ref:`string(REGEX) <Regex Specification>`.
This option tells CTest to run only the tests whose labels match the
- given regular expression.
+ given regular expression. When more than one ``-L`` option is given,
+ a test will only be run if each regular expression matches at least one
+ of the test's labels (i.e. the multiple ``-L`` labels form an ``AND``
+ relationship). See `Label Matching`_.
``-R <regex>, --tests-regex <regex>``
Run tests matching regular expression.
@@ -173,7 +183,10 @@ Options
Exclude tests with labels matching regular expression.
This option tells CTest to NOT run the tests whose labels match the
- given regular expression.
+ given regular expression. When more than one ``-LE`` option is given,
+ a test will only be excluded if each regular expression matches at least one
+ of the test's labels (i.e. the multiple ``-LE`` labels form an ``AND``
+ relationship). See `Label Matching`_.
``-FA <regex>, --fixture-exclude-any <regex>``
Exclude fixtures matching ``<regex>`` from automatically adding any tests to
@@ -309,11 +322,13 @@ Options
Set the interactive mode to ``0`` or ``1``.
This option causes CTest to run tests in either an interactive mode
- or a non-interactive mode. On Windows this means that in
- non-interactive mode, all system debug pop up windows are blocked.
- In dashboard mode (``Experimental``, ``Nightly``, ``Continuous``), the default
- is non-interactive. When just running tests not for a dashboard the
- default is to allow popups and interactive debugging.
+ or a non-interactive mode. In dashboard mode (``Experimental``, ``Nightly``,
+ ``Continuous``), the default is non-interactive. In non-interactive mode,
+ the environment variable :envvar:`DASHBOARD_TEST_FROM_CTEST` is set.
+
+ Prior to CMake 3.11, interactive mode on Windows allowed system debug
+ 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``
Disable timing summary information for labels.
@@ -398,6 +413,46 @@ Specify the directory in which to look for tests.
.. include:: OPTIONS_HELP.txt
+.. _`Label Matching`:
+
+Label Matching
+==============
+
+Tests may have labels attached to them. Tests may be included
+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
+test run, each regular expression must match at least one
+label. Using more than one ``-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.
+
+If a test has no labels attached to it, then ``-L`` will never
+include that test, and ``-LE`` will never exclude that test.
+As an example of tests with labels, consider five tests,
+with the following labels:
+
+* *test1* has labels *tuesday* and *production*
+* *test2* has labels *tuesday* and *test*
+* *test3* has labels *wednesday* and *production*
+* *test4* has label *wednesday*
+* *test5* has labels *friday* and *test*
+
+Running ``ctest`` with ``-L tuesday -L test`` will select *test2*, which has
+both labels. Running CTest with ``-L test`` will select *test2* and
+*test5*, because both of them have a label that matches that regular
+expression.
+
+Because the matching works with regular expressions, take note that
+running CTest with ``-L es`` will match all five tests.
+To select the *tuesday* and *wednesday* tests together, use a single
+regular expression that matches either of them, like ``-L "tue|wed"``.
+
.. _`Label and Subproject Summary`:
Label and Subproject Summary
@@ -1043,6 +1098,8 @@ Configuration settings include:
* `CTest Script`_ variable: :variable:`CTEST_TEST_TIMEOUT`
* :module:`CTest` module variable: ``DART_TESTING_TIMEOUT``
+To report extra test values to CDash, see :ref:`Additional Test Measurements`.
+
.. _`CTest Coverage Step`:
CTest Coverage Step
@@ -1619,4 +1676,4 @@ See Also
.. include:: LINKS.txt
-.. _`CDash`: http://cdash.org/
+_`CDash`: https://cdash.org
diff --git a/Help/manual/presets/example.json b/Help/manual/presets/example.json
index dfc2910a2..b08445a47 100644
--- a/Help/manual/presets/example.json
+++ b/Help/manual/presets/example.json
@@ -1,8 +1,8 @@
{
- "version": 2,
+ "version": 3,
"cmakeMinimumRequired": {
"major": 3,
- "minor": 20,
+ "minor": 21,
"patch": 0
},
"configurePresets": [
@@ -35,6 +35,17 @@
"displayName": "Ninja Multi-Config",
"description": "Default build using Ninja Multi-Config generator",
"generator": "Ninja Multi-Config"
+ },
+ {
+ "name": "windows-only",
+ "inherits": "default",
+ "displayName": "Windows-only configuration",
+ "description": "This build is only available on Windows",
+ "condition": {
+ "type": "equals",
+ "lhs": "${hostSystemName}",
+ "rhs": "Windows"
+ }
}
],
"buildPresets": [
diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json
index f8faf3dd7..767e80b6b 100644
--- a/Help/manual/presets/schema.json
+++ b/Help/manual/presets/schema.json
@@ -11,7 +11,7 @@
},
"cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"},
"vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresets"}
+ "configurePresets": { "$ref": "#/definitions/configurePresetsV1"}
},
"additionalProperties": false
},
@@ -23,9 +23,23 @@
},
"cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"},
"vendor": { "$ref": "#/definitions/vendor" },
- "configurePresets": { "$ref": "#/definitions/configurePresets"},
- "buildPresets": { "$ref": "#/definitions/buildPresets"},
- "testPresets": { "$ref": "#/definitions/testPresets"}
+ "configurePresets": { "$ref": "#/definitions/configurePresetsV1"},
+ "buildPresets": { "$ref": "#/definitions/buildPresetsV2"},
+ "testPresets": { "$ref": "#/definitions/testPresetsV2"}
+ },
+ "additionalProperties": false
+ },
+ {
+ "properties": {
+ "version": {
+ "const": 3,
+ "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/buildPresetsV3"},
+ "testPresets": { "$ref": "#/definitions/testPresetsV3"}
},
"additionalProperties": false
}
@@ -58,7 +72,34 @@
"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, the keys should be a vendor-specific domain name followed by a /-separated path. For example, the Example IDE 1.0 could use example.com/ExampleIDE/1.0. The value of each field can be anything desired by the vendor, though will typically be a map.",
"properties": {}
},
- "configurePresets": {
+ "configurePresetsItemsV3": {
+ "type": "array",
+ "description": "A configure preset object.",
+ "items": {
+ "type": "object",
+ "description": "A configure preset object.",
+ "properties": {
+ "binaryDir": {
+ "type": "string",
+ "description": "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 specified, the path is calculated using regular methods."
+ },
+ "generator": {
+ "type": "string",
+ "description": "An optional string representing the generator to use for the preset. If generator is not specified, the normal generator discovery procedure is used. 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."
+ },
+ "toolchainFile": {
+ "type": "string",
+ "description": "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, relative to the source directory."
+ },
+ "installDir": {
+ "type": "string",
+ "description": "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."
+ },
+ "condition": { "$ref": "#/definitions/topCondition" }
+ }
+ }
+ },
+ "configurePresetsItemsV1": {
"type": "array",
"description": "An optional array of configure preset objects.",
"items": {
@@ -302,6 +343,37 @@
},
"additionalProperties": false
}
+ }
+ }
+ },
+ "configurePresetsV3": {
+ "type": "array",
+ "description": "An optional array of configure preset objects.",
+ "allOf": [
+ { "$ref": "#/definitions/configurePresetsItemsV1" },
+ { "$ref": "#/definitions/configurePresetsItemsV3" }
+ ],
+ "items": {
+ "properties": {
+ "name": {},
+ "hidden": {},
+ "inherits": {},
+ "vendor": {},
+ "displayName": {},
+ "description": {},
+ "generator": {},
+ "architecture": {},
+ "toolset": {},
+ "toolchainFile": {},
+ "binaryDir": {},
+ "installDir": {},
+ "cmakeExecutable": {},
+ "cacheVariables": {},
+ "environment": {},
+ "warnings": {},
+ "errors": {},
+ "debug": {},
+ "condition": {}
},
"required": [
"name"
@@ -309,7 +381,48 @@
"additionalProperties": false
}
},
- "buildPresets": {
+ "configurePresetsV1": {
+ "type": "array",
+ "description": "An optional array of configure preset objects.",
+ "allOf": [
+ { "$ref": "#/definitions/configurePresetsItemsV1" }
+ ],
+ "items": {
+ "properties": {
+ "name": {},
+ "hidden": {},
+ "inherits": {},
+ "vendor": {},
+ "displayName": {},
+ "description": {},
+ "generator": {},
+ "architecture": {},
+ "toolset": {},
+ "binaryDir": {},
+ "cmakeExecutable": {},
+ "cacheVariables": {},
+ "environment": {},
+ "warnings": {},
+ "errors": {},
+ "debug": {}
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "buildPresetsItemsV3": {
+ "type": "array",
+ "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 2 and higher.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "condition": { "$ref": "#/definitions/topCondition" }
+ }
+ }
+ },
+ "buildPresetsItemsV2": {
"type": "array",
"description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 2 and higher.",
"items": {
@@ -427,11 +540,84 @@
},
"required": [
"name"
+ ]
+ }
+ },
+ "buildPresetsV3": {
+ "type": "array",
+ "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 2 and higher.",
+ "allOf": [
+ { "$ref": "#/definitions/buildPresetsItemsV3" },
+ { "$ref": "#/definitions/buildPresetsItemsV2" }
+ ],
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {},
+ "hidden": {},
+ "inherits": {},
+ "configurePreset": {},
+ "vendor": {},
+ "displayName": {},
+ "description": {},
+ "inheritConfigureEnvironment": {},
+ "environment": {},
+ "jobs": {},
+ "targets": {},
+ "configuration": {},
+ "cleanFirst": {},
+ "verbose": {},
+ "nativeToolOptions": {},
+ "condition": {}
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "buildPresetsV2": {
+ "type": "array",
+ "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 2 and higher.",
+ "allOf": [
+ { "$ref": "#/definitions/buildPresetsItemsV2" }
+ ],
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {},
+ "hidden": {},
+ "inherits": {},
+ "configurePreset": {},
+ "vendor": {},
+ "displayName": {},
+ "description": {},
+ "inheritConfigureEnvironment": {},
+ "environment": {},
+ "jobs": {},
+ "targets": {},
+ "configuration": {},
+ "cleanFirst": {},
+ "verbose": {},
+ "nativeToolOptions": {}
+ },
+ "required": [
+ "name"
],
"additionalProperties": false
}
},
- "testPresets": {
+ "testPresetsItemsV3": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 2 and higher.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "condition": { "$ref": "#/definitions/topCondition" }
+ }
+ }
+ },
+ "testPresetsItemsV2": {
"type": "array",
"description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 2 and higher.",
"items": {
@@ -743,9 +929,312 @@
},
"required": [
"name"
+ ]
+ }
+ },
+ "testPresetsV3": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 2 and higher.",
+ "allOf": [
+ { "$ref": "#/definitions/testPresetsItemsV2" },
+ { "$ref": "#/definitions/testPresetsItemsV3" }
+ ],
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {},
+ "hidden": {},
+ "inherits": {},
+ "configurePreset": {},
+ "vendor": {},
+ "displayName": {},
+ "description": {},
+ "inheritConfigureEnvironment": {},
+ "environment": {},
+ "configuration": {},
+ "overwriteConfigurationFile": {},
+ "output": {},
+ "filter": {},
+ "execution": {},
+ "condition": {}
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "testPresetsV2": {
+ "type": "array",
+ "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 2 and higher.",
+ "allOf": [
+ { "$ref": "#/definitions/testPresetsItemsV2" }
+ ],
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {},
+ "hidden": {},
+ "inherits": {},
+ "configurePreset": {},
+ "vendor": {},
+ "displayName": {},
+ "description": {},
+ "inheritConfigureEnvironment": {},
+ "environment": {},
+ "configuration": {},
+ "overwriteConfigurationFile": {},
+ "output": {},
+ "filter": {},
+ "execution": {}
+ },
+ "required": [
+ "name"
],
"additionalProperties": false
}
+ },
+ "condition": {
+ "anyOf": [
+ {
+ "type": "boolean",
+ "description": "A boolean which provides a constant value for the condition's evaluation."
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "const"
+ },
+ "value": {
+ "type": "boolean",
+ "description": "A required boolean which provides a constant value for the condition's evaluation."
+ }
+ },
+ "required": [
+ "type",
+ "value"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "equals"
+ },
+ "lhs": {
+ "type": "string",
+ "description": "First string to compare. This field supports macro expansion."
+ },
+ "rhs": {
+ "type": "string",
+ "description": "Second string to compare. This field supports macro expansion."
+ }
+ },
+ "required": [
+ "type",
+ "lhs",
+ "rhs"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "notEquals"
+ },
+ "lhs": {
+ "type": "string",
+ "description": "First string to compare. This field supports macro expansion."
+ },
+ "rhs": {
+ "type": "string",
+ "description": "Second string to compare. This field supports macro expansion."
+ }
+ },
+ "required": [
+ "type",
+ "lhs",
+ "rhs"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "inList"
+ },
+ "string": {
+ "type": "string",
+ "description": "A required string to search for. This field supports macro expansion."
+ },
+ "list": {
+ "type": "array",
+ "description": "A required list of strings to search. This field supports macro expansion, and uses short-circuit evaluation.",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "type",
+ "string",
+ "list"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "notInList"
+ },
+ "string": {
+ "type": "string",
+ "description": "A required string to search for. This field supports macro expansion."
+ },
+ "list": {
+ "type": "array",
+ "description": "A required list of strings to search. This field supports macro expansion, and uses short-circuit evaluation.",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "type",
+ "string",
+ "list"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "matches"
+ },
+ "string": {
+ "type": "string",
+ "description": "A required string to search. This field supports macro expansion."
+ },
+ "regex": {
+ "type": "string",
+ "description": "A required regular expression to search for. This field supports macro expansion."
+ }
+ },
+ "required": [
+ "type",
+ "string",
+ "regex"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "notMatches"
+ },
+ "string": {
+ "type": "string",
+ "description": "A required string to search. This field supports macro expansion."
+ },
+ "regex": {
+ "type": "string",
+ "description": "A required regular expression to search for. This field supports macro expansion."
+ }
+ },
+ "required": [
+ "type",
+ "string",
+ "regex"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "anyOf"
+ },
+ "conditions": {
+ "type": "array",
+ "description": "A required array of condition objects. These conditions use short-circuit evaluation.",
+ "items": { "$ref": "#/definitions/condition" }
+ }
+ },
+ "required": [
+ "type",
+ "conditions"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "allOf"
+ },
+ "conditions": {
+ "type": "array",
+ "description": "A required array of condition objects. These conditions use short-circuit evaluation.",
+ "items": { "$ref": "#/definitions/condition" }
+ }
+ },
+ "required": [
+ "type",
+ "conditions"
+ ],
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "A required string specifying the type of the condition.",
+ "const": "not"
+ },
+ "condition": { "$ref": "#/definitions/condition" }
+ },
+ "required": [
+ "type",
+ "condition"
+ ],
+ "additionalProperties": false
+ }
+ ]
+ },
+ "topCondition": {
+ "anyOf": [
+ { "$ref": "#/definitions/condition" },
+ {
+ "type": "null",
+ "description": "Null indicates that the condition always evaluates to true and is not inherited."
+ }
+ ]
}
}
}
diff --git a/Help/module/FindMsys.rst b/Help/module/FindMsys.rst
new file mode 100644
index 000000000..fc5495ce7
--- /dev/null
+++ b/Help/module/FindMsys.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindMsys.cmake
diff --git a/Help/policy/CMP0102.rst b/Help/policy/CMP0102.rst
index 78b558480..08024bfd3 100644
--- a/Help/policy/CMP0102.rst
+++ b/Help/policy/CMP0102.rst
@@ -22,6 +22,8 @@ already exist in the cache.
This policy was introduced in CMake version 3.17. 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.
+when this policy is not set and simply uses ``OLD`` behavior. See
+documentation of the :variable:`CMAKE_POLICY_WARNING_CMP0102
+<CMAKE_POLICY_WARNING_CMP<NNNN>>` variable to control the warning.
.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0104.rst b/Help/policy/CMP0104.rst
index 7c7a16e37..b125729dd 100644
--- a/Help/policy/CMP0104.rst
+++ b/Help/policy/CMP0104.rst
@@ -41,7 +41,7 @@ Examples
.. code-block:: cmake
- set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES 35 50 72)
+ set_target_properties(tgt PROPERTIES CUDA_ARCHITECTURES "35;50;72")
Generates code for real and virtual architectures ``30``, ``50`` and ``72``.
diff --git a/Help/policy/CMP0110.rst b/Help/policy/CMP0110.rst
index 25a00089f..6977d41e5 100644
--- a/Help/policy/CMP0110.rst
+++ b/Help/policy/CMP0110.rst
@@ -8,7 +8,7 @@ CMP0110
:command:`add_test` can now (officially) create tests with whitespace and
other special characters in its name. Before CMake version 3.19 that was not
allowed, however, it was possible to work around this limitation by explicitly
-putting escaped quotes arount the test's name in the ``add_test`` command.
+putting escaped quotes around the test's name in the ``add_test`` command.
Although never officially supported several projects in the wild found and
implemented this workaround. However, the new change which officially allows
diff --git a/Help/policy/CMP0121.rst b/Help/policy/CMP0121.rst
new file mode 100644
index 000000000..326e7d595
--- /dev/null
+++ b/Help/policy/CMP0121.rst
@@ -0,0 +1,21 @@
+CMP0121
+-------
+
+.. versionadded:: 3.21
+
+The :command:`list` command now detects invalid indices.
+
+Prior to CMake version 3.21, the :command:`list` command's ``GET``,
+``INSERT``, ``SUBLIST``, and ``REMOVE_AT`` subcommands did not detect invalid
+index arguments.
+
+The ``OLD`` behavior of this policy is for invalid indices to be treated as
+their integer value (if any) at the start of the string. For example,
+``2good4you`` is a ``2`` and ``not_an_integer`` is a ``0``. The ``NEW``
+behavior is for invalid indices to trigger an error.
+
+This policy was introduced in CMake version 3.21. 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/CMP0122.rst b/Help/policy/CMP0122.rst
new file mode 100644
index 000000000..1ff8c4862
--- /dev/null
+++ b/Help/policy/CMP0122.rst
@@ -0,0 +1,17 @@
+CMP0122
+-------
+
+.. versionadded:: 3.21
+
+:module:`UseSWIG` use library name conventions for ``CSharp`` language.
+
+Starting with CMake 3.21, :module:`UseSWIG` generates now a library using
+default naming conventions. This policy provides compatibility with projects
+that expect the legacy behavior.
+
+This policy was introduced in CMake version 3.21. 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/CMP0123.rst b/Help/policy/CMP0123.rst
new file mode 100644
index 000000000..e09b5ec97
--- /dev/null
+++ b/Help/policy/CMP0123.rst
@@ -0,0 +1,32 @@
+CMP0123
+-------
+
+.. versionadded:: 3.21
+
+``ARMClang`` cpu/arch compile and link flags must be set explicitly.
+
+CMake 3.20 and lower automatically maps the :variable:`CMAKE_SYSTEM_PROCESSOR`
+variable and an undocumented ``CMAKE_SYSTEM_ARCH`` to compile and link options
+for ``ARMClang``. For example, the ``-mcpu=cortex-m33`` flag is added when
+:variable:`CMAKE_SYSTEM_PROCESSOR` equals ``cortex-m33``. CMake requires
+projects to set either variable or it raises a fatal error. However, the
+project may need to additionally specify CPU features using e.g.
+``-mcpu=cortex-m33+nodsp``, conflicting with the ``-mcpu=cortex-m33`` added
+by CMake. This results in either link errors or unusable binaries.
+
+CMake 3.21 and above prefer instead to not add any cpu/arch compile and link
+flags automatically. Instead, projects must specify them explicitly.
+This policy provides compatibility for projects that have not been updated.
+
+The ``OLD`` behavior of this policy requires projects that use ``ARMClang``
+to set either :variable:`CMAKE_SYSTEM_PROCESSOR` or ``CMAKE_SYSTEM_ARCH``
+and it automatically adds a compile option ``-mcpu=`` or ``-march=`` and
+a link option ``--cpu=`` based on those variables. The ``NEW`` behavior
+does not add compile or link options, and projects are responsible for
+setting correct options.
+
+This policy was introduced in CMake version 3.21. 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/CMP0124.rst b/Help/policy/CMP0124.rst
new file mode 100644
index 000000000..88d03e35d
--- /dev/null
+++ b/Help/policy/CMP0124.rst
@@ -0,0 +1,20 @@
+CMP0124
+-------
+
+.. versionadded:: 3.21
+
+The loop variables created by :command:`foreach` command have now their scope
+restricted to the loop scope.
+
+Starting with CMake 3.21, the :command:`foreach` command ensures that the loop
+variables have their scope restricted to the loop scope.
+
+The ``OLD`` behavior for this policy let the loop variables to exist, with an
+empty value, in the outer scope of loop scope.
+
+This policy was introduced in CMake version 3.21. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn when the policy
+is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0125.rst b/Help/policy/CMP0125.rst
new file mode 100644
index 000000000..19571dc25
--- /dev/null
+++ b/Help/policy/CMP0125.rst
@@ -0,0 +1,25 @@
+CMP0125
+-------
+
+.. versionadded:: 3.21
+
+The :command:`find_file`, :command:`find_path`, :command:`find_library` and
+:command:`find_program` commands handle cache variables in the same way
+regardless of whether they are defined on the command line, with or without a
+type, or using the :command:`set` command.
+
+Starting with CMake 3.21, the :command:`find_file`, :command:`find_path`,
+:command:`find_library`, and :command:`find_program` commands ensure that the
+cache variables will be used in the same way regardless how they were defined
+and the result will be always successful if the searched artifact exists.
+
+The ``OLD`` behavior for this policy is to have the find commands' behaviors
+differ depending on how the cache variable is defined. The ``NEW`` behavior for
+this policy is to have consistent behavior.
+
+This policy was introduced in CMake version 3.21. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn when the policy
+is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0126.rst b/Help/policy/CMP0126.rst
new file mode 100644
index 000000000..0ced8fa5a
--- /dev/null
+++ b/Help/policy/CMP0126.rst
@@ -0,0 +1,22 @@
+CMP0126
+-------
+
+.. versionadded:: 3.21
+
+The :command:`set(CACHE)` does not remove a normal variable of the same name.
+
+Starting with CMake 3.21, the :command:`set(CACHE)` does not remove, in the
+current scope, any normal variable with the same name.
+
+The ``OLD`` behavior for this policy is to have the :command:`set(CACHE)`
+command removing the normal variable of the same name, if any. The ``NEW``
+behavior for this policy is to keep the normal variable of the same name.
+
+This policy was introduced in CMake version 3.21. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn when the policy
+is not set and simply uses ``OLD`` behavior. See documentation of the
+:variable:`CMAKE_POLICY_WARNING_CMP0126 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
+variable to control the warning.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/prop_dir/BUILDSYSTEM_TARGETS.rst b/Help/prop_dir/BUILDSYSTEM_TARGETS.rst
index 5c5893dfc..c998488b4 100644
--- a/Help/prop_dir/BUILDSYSTEM_TARGETS.rst
+++ b/Help/prop_dir/BUILDSYSTEM_TARGETS.rst
@@ -11,3 +11,5 @@ and :command:`add_custom_target` commands. The list does not include any
:ref:`Interface Libraries`. Each entry in the list is the logical name
of a target, suitable to pass to the :command:`get_property` command
``TARGET`` option.
+
+See also the :prop_dir:`IMPORTED_TARGETS` directory property.
diff --git a/Help/prop_dir/IMPORTED_TARGETS.rst b/Help/prop_dir/IMPORTED_TARGETS.rst
new file mode 100644
index 000000000..fea8a93d4
--- /dev/null
+++ b/Help/prop_dir/IMPORTED_TARGETS.rst
@@ -0,0 +1,14 @@
+IMPORTED_TARGETS
+----------------
+
+.. versionadded:: 3.21
+
+This read-only directory property contains a
+:ref:`semicolon-separated list <CMake Language Lists>` of
+:ref:`Imported Targets` added in the directory by calls to the
+:command:`add_library` and :command:`add_executable` commands.
+Each entry in the list is the logical name of a target, suitable
+to pass to the :command:`get_property` command ``TARGET`` option
+when called in the same directory.
+
+See also the :prop_dir:`BUILDSYSTEM_TARGETS` directory property.
diff --git a/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst
index 2e3232062..07c732bd4 100644
--- a/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst
+++ b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst
@@ -3,15 +3,16 @@ AUTOGEN_SOURCE_GROUP
.. versionadded:: 3.9
-Name of the :command:`source_group` for :prop_tgt:`AUTOMOC` and
-:prop_tgt:`AUTORCC` generated files.
+Name of the :command:`source_group` for :prop_tgt:`AUTOMOC`,
+:prop_tgt:`AUTORCC` and :prop_tgt:`AUTOUIC` generated files.
-Files generated by :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` are not always
-known at configure time and therefore can't be passed to
-:command:`source_group`.
-:prop_gbl:`AUTOGEN_SOURCE_GROUP` an be used instead to generate or select
-a source group for :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` generated files.
+Files generated by :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTORCC` and
+:prop_tgt:`AUTOUIC` are not always known at configure time and therefore can't
+be passed to :command:`source_group`.
+:prop_gbl:`AUTOGEN_SOURCE_GROUP` can be used instead to generate or select
+a source group for :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTORCC` and
+:prop_tgt:`AUTOUIC` generated files.
-For :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` specific overrides see
-:prop_gbl:`AUTOMOC_SOURCE_GROUP` and :prop_gbl:`AUTORCC_SOURCE_GROUP`
-respectively.
+For :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTORCC` and :prop_tgt:`AUTOUIC` specific
+overrides see :prop_gbl:`AUTOMOC_SOURCE_GROUP`, :prop_gbl:`AUTORCC_SOURCE_GROUP`
+and :prop_gbl:`AUTOUIC_SOURCE_GROUP` respectively.
diff --git a/Help/prop_gbl/AUTOUIC_SOURCE_GROUP.rst b/Help/prop_gbl/AUTOUIC_SOURCE_GROUP.rst
new file mode 100644
index 000000000..79ebfe0ec
--- /dev/null
+++ b/Help/prop_gbl/AUTOUIC_SOURCE_GROUP.rst
@@ -0,0 +1,9 @@
+AUTOUIC_SOURCE_GROUP
+--------------------
+
+.. versionadded:: 3.21
+
+Name of the :command:`source_group` for :prop_tgt:`AUTOUIC` generated files.
+
+When set this is used instead of :prop_gbl:`AUTOGEN_SOURCE_GROUP` for
+files generated by :prop_tgt:`AUTOUIC`.
diff --git a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst
index 7166381aa..2bd0febea 100644
--- a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst
+++ b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst
@@ -24,6 +24,12 @@ The features known to this version of CMake are:
``c_std_11``
Compiler mode is at least C 11.
+``c_std_17``
+ Compiler mode is at least C 17.
+
+``c_std_23``
+ Compiler mode is at least C 23.
+
``c_function_prototypes``
Function prototypes, as defined in ``ISO/IEC 9899:1990``.
diff --git a/Help/prop_sf/COMPILE_FLAGS.rst b/Help/prop_sf/COMPILE_FLAGS.rst
index c211b89ac..eefe7bff3 100644
--- a/Help/prop_sf/COMPILE_FLAGS.rst
+++ b/Help/prop_sf/COMPILE_FLAGS.rst
@@ -4,8 +4,11 @@ COMPILE_FLAGS
Additional flags to be added when compiling this source file.
The ``COMPILE_FLAGS`` property, managed as a string, sets additional compiler
-flags used to build source files. Use :prop_sf:`COMPILE_DEFINITIONS` to pass
-additional preprocessor definitions.
+flags used that will be added to the list of compile flags when this source
+file builds. The flags will be added after target-wide flags (except in
+some cases not supported by the :generator:`Visual Studio 9 2008` generator).
+
+Use :prop_sf:`COMPILE_DEFINITIONS` to pass additional preprocessor definitions.
Contents of ``COMPILE_FLAGS`` may use "generator expressions"
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
diff --git a/Help/prop_sf/COMPILE_OPTIONS.rst b/Help/prop_sf/COMPILE_OPTIONS.rst
index a694c3e61..84c543a2c 100644
--- a/Help/prop_sf/COMPILE_OPTIONS.rst
+++ b/Help/prop_sf/COMPILE_OPTIONS.rst
@@ -5,9 +5,10 @@ COMPILE_OPTIONS
List of additional options to pass to the compiler.
-This property holds a :ref:`semicolon-separated list <CMake Language Lists>` of options
-and will be added to the list of compile flags when this
-source file builds.
+This property holds a :ref:`semicolon-separated list <CMake Language Lists>`
+of options and will be added to the list of compile flags when this source
+file builds. The options will be added after target-wide options (except in
+some cases not supported by the :generator:`Visual Studio 9 2008` generator).
Contents of ``COMPILE_OPTIONS`` may use "generator expressions" with the
syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
diff --git a/Help/prop_sf/GENERATED.rst b/Help/prop_sf/GENERATED.rst
index 6ef458022..216dfe8da 100644
--- a/Help/prop_sf/GENERATED.rst
+++ b/Help/prop_sf/GENERATED.rst
@@ -32,9 +32,10 @@ The :ref:`Makefile Generators` will remove ``GENERATED`` files during
``make clean``.
Generated sources may be hidden in some IDE tools, while in others they might
-be shown. For the special case of sources generated by CMake's :prop_tgt:`AUTOMOC`
-or :prop_tgt:`AUTORCC` functionality, the :prop_gbl:`AUTOGEN_SOURCE_GROUP`,
-:prop_gbl:`AUTOMOC_SOURCE_GROUP` and :prop_gbl:`AUTORCC_SOURCE_GROUP` target
+be shown. For the special case of sources generated by CMake's :prop_tgt:`AUTOMOC`,
+:prop_tgt:`AUTORCC` or :prop_tgt:`AUTOUIC` functionality, the
+:prop_gbl:`AUTOGEN_SOURCE_GROUP`, :prop_gbl:`AUTOMOC_SOURCE_GROUP`,
+:prop_gbl:`AUTORCC_SOURCE_GROUP` and :prop_gbl:`AUTOUIC_SOURCE_GROUP` target
properties may influence where the generated sources are grouped in the project's
file lists.
diff --git a/Help/prop_sf/LANGUAGE.rst b/Help/prop_sf/LANGUAGE.rst
index f14c176ca..a9b563870 100644
--- a/Help/prop_sf/LANGUAGE.rst
+++ b/Help/prop_sf/LANGUAGE.rst
@@ -6,8 +6,8 @@ Specify the programming language in which a source file is written.
A property that can be set to indicate what programming language the
source file is. If it is not set the language is determined based on
the file extension. Typical values are ``CXX`` (i.e. C++), ``C``,
-``CSharp``, ``CUDA``, ``Fortran``, ``ISPC``, and ``ASM``. Setting this
-property for a file means this file will be compiled. Do not set this
+``CSharp``, ``CUDA``, ``Fortran``, ``HIP``, ``ISPC``, and ``ASM``. Setting
+this property for a file means this file will be compiled. Do not set this
for headers or files that should not be compiled.
.. versionchanged:: 3.20
diff --git a/Help/prop_test/FAIL_REGULAR_EXPRESSION.rst b/Help/prop_test/FAIL_REGULAR_EXPRESSION.rst
index facf90255..1ec451760 100644
--- a/Help/prop_test/FAIL_REGULAR_EXPRESSION.rst
+++ b/Help/prop_test/FAIL_REGULAR_EXPRESSION.rst
@@ -1,7 +1,8 @@
FAIL_REGULAR_EXPRESSION
-----------------------
-If the output matches this regular expression the test will fail.
+If the output matches this regular expression the test will fail,
+regardless of the process exit code.
If set, if the output matches one of specified regular expressions,
the test will fail. Example:
@@ -13,3 +14,6 @@ the test will fail. Example:
)
``FAIL_REGULAR_EXPRESSION`` expects a list of regular expressions.
+
+See also the :prop_test:`PASS_REGULAR_EXPRESSION` and
+:prop_test:`SKIP_REGULAR_EXPRESSION` test properties.
diff --git a/Help/prop_test/FIXTURES_REQUIRED.rst b/Help/prop_test/FIXTURES_REQUIRED.rst
index d92808a63..f85083069 100644
--- a/Help/prop_test/FIXTURES_REQUIRED.rst
+++ b/Help/prop_test/FIXTURES_REQUIRED.rst
@@ -35,9 +35,9 @@ The concept of a fixture is different to that of a resource specified by
set of tests which share setup and cleanup requirements, whereas a resource
lock has the effect of ensuring a particular set of tests do not run in
parallel. Some situations may need both, such as setting up a database,
-serialising test access to that database and deleting the database again at the
+serializing test access to that database and deleting the database again at the
end. For such cases, tests would populate both ``FIXTURES_REQUIRED`` and
-:prop_test:`RESOURCE_LOCK` to combine the two behaviours. Names used for
+:prop_test:`RESOURCE_LOCK` to combine the two behaviors. Names used for
:prop_test:`RESOURCE_LOCK` have no relationship with names of fixtures, so note
that a resource lock does not imply a fixture and vice versa.
diff --git a/Help/prop_test/PASS_REGULAR_EXPRESSION.rst b/Help/prop_test/PASS_REGULAR_EXPRESSION.rst
index 0cd621526..96468c02a 100644
--- a/Help/prop_test/PASS_REGULAR_EXPRESSION.rst
+++ b/Help/prop_test/PASS_REGULAR_EXPRESSION.rst
@@ -2,6 +2,7 @@ PASS_REGULAR_EXPRESSION
-----------------------
The output must match this regular expression for the test to pass.
+The process exit code is ignored.
If set, the test output will be checked against the specified regular
expressions and at least one of the regular expressions has to match,
@@ -14,3 +15,6 @@ otherwise the test will fail. Example:
)
``PASS_REGULAR_EXPRESSION`` expects a list of regular expressions.
+
+See also the :prop_test:`FAIL_REGULAR_EXPRESSION` and
+:prop_test:`SKIP_REGULAR_EXPRESSION` test properties.
diff --git a/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst b/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst
index 46c4363c4..60038e440 100644
--- a/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst
+++ b/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst
@@ -16,4 +16,6 @@ the test will be marked as skipped. Example:
``SKIP_REGULAR_EXPRESSION`` expects a list of regular expressions.
-See also the :prop_test:`SKIP_RETURN_CODE` property.
+See also the :prop_test:`SKIP_RETURN_CODE`,
+:prop_test:`PASS_REGULAR_EXPRESSION`, and :prop_test:`FAIL_REGULAR_EXPRESSION`
+test properties.
diff --git a/Help/prop_tgt/COMPILE_OPTIONS.rst b/Help/prop_tgt/COMPILE_OPTIONS.rst
index 0cd683610..0fd6aac60 100644
--- a/Help/prop_tgt/COMPILE_OPTIONS.rst
+++ b/Help/prop_tgt/COMPILE_OPTIONS.rst
@@ -3,9 +3,13 @@ COMPILE_OPTIONS
List of options to pass to the compiler.
-This property holds a :ref:`semicolon-separated list <CMake Language Lists>` of options
-specified so far for its target. Use the :command:`target_compile_options`
-command to append more options.
+This property holds a :ref:`semicolon-separated list <CMake Language Lists>`
+of options specified so far for its target. Use the
+:command:`target_compile_options` command to append more options.
+The options will be added after after flags in the
+:variable:`CMAKE_<LANG>_FLAGS` and :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>`
+variables, but before those propagated from dependencies by the
+:prop_tgt:`INTERFACE_COMPILE_OPTIONS` property.
This property is initialized by the :prop_dir:`COMPILE_OPTIONS` directory
property when a target is created, and is used by the generators to set
@@ -15,3 +19,5 @@ Contents of ``COMPILE_OPTIONS`` may use "generator expressions" with the
syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
for available expressions. See the :manual:`cmake-buildsystem(7)` manual
for more on defining buildsystem properties.
+
+.. include:: ../command/OPTIONS_SHELL.txt
diff --git a/Help/prop_tgt/CUDA_ARCHITECTURES.rst b/Help/prop_tgt/CUDA_ARCHITECTURES.rst
index d56b76908..a3191e8e0 100644
--- a/Help/prop_tgt/CUDA_ARCHITECTURES.rst
+++ b/Help/prop_tgt/CUDA_ARCHITECTURES.rst
@@ -25,7 +25,7 @@ Examples
.. code-block:: cmake
- set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES 35 50 72)
+ set_target_properties(tgt PROPERTIES CUDA_ARCHITECTURES "35;50;72")
Generates code for real and virtual architectures ``30``, ``50`` and ``72``.
diff --git a/Help/prop_tgt/CUDA_STANDARD.rst b/Help/prop_tgt/CUDA_STANDARD.rst
index 6517035a2..5ef57be70 100644
--- a/Help/prop_tgt/CUDA_STANDARD.rst
+++ b/Help/prop_tgt/CUDA_STANDARD.rst
@@ -9,7 +9,29 @@ This property specifies the CUDA/C++ standard whose features are requested
to build this target. For some compilers, this results in adding a
flag such as ``-std=gnu++11`` to the compile line.
-Supported values are ``98``, ``03``, ``11``, ``14``, ``17``, ``20``, ``23``.
+Supported values are:
+
+``98``
+ CUDA C++98
+
+``11``
+ CUDA C++11
+
+``14``
+ CUDA C++14
+
+``17``
+ CUDA C++17
+
+``20``
+ .. versionadded:: 3.12
+
+ CUDA C++20
+
+``23``
+ .. versionadded:: 3.20
+
+ CUDA C++23
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
diff --git a/Help/prop_tgt/CXX_STANDARD.rst b/Help/prop_tgt/CXX_STANDARD.rst
index be0dab565..b10d20173 100644
--- a/Help/prop_tgt/CXX_STANDARD.rst
+++ b/Help/prop_tgt/CXX_STANDARD.rst
@@ -11,7 +11,31 @@ flag such as ``-std=gnu++11`` to the compile line. For compilers that
have no notion of a standard level, such as Microsoft Visual C++ before
2015 Update 3, this has no effect.
-Supported values are ``98``, ``11``, ``14``, ``17``, ``20``, ``23``.
+Supported values are:
+
+``98``
+ C++98
+
+``11``
+ C++11
+
+``14``
+ C++14
+
+``17``
+ .. versionadded:: 3.8
+
+ C++17
+
+``20``
+ .. versionadded:: 3.12
+
+ C++20
+
+``23``
+ .. versionadded:: 3.20
+
+ C++23
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
diff --git a/Help/prop_tgt/C_STANDARD.rst b/Help/prop_tgt/C_STANDARD.rst
index 3f0d242f4..ecba2a8f1 100644
--- a/Help/prop_tgt/C_STANDARD.rst
+++ b/Help/prop_tgt/C_STANDARD.rst
@@ -11,7 +11,26 @@ flag such as ``-std=gnu11`` to the compile line. For compilers that
have no notion of a C standard level, such as Microsoft Visual C++ before
VS 16.7, this property has no effect.
-Supported values are ``90``, ``99`` and ``11``.
+Supported values are:
+
+``90``
+ C89/C90
+
+``99``
+ C99
+
+``11``
+ C11
+
+``17``
+ .. versionadded:: 3.21
+
+ C17
+
+``23``
+ .. versionadded:: 3.21
+
+ C23
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
diff --git a/Help/prop_tgt/HIP_ARCHITECTURES.rst b/Help/prop_tgt/HIP_ARCHITECTURES.rst
new file mode 100644
index 000000000..06f956b18
--- /dev/null
+++ b/Help/prop_tgt/HIP_ARCHITECTURES.rst
@@ -0,0 +1,27 @@
+HIP_ARCHITECTURES
+-----------------
+
+.. versionadded:: 3.21
+
+List of AMD GPU architectures to generate device code for.
+
+A non-empty false value (e.g. ``OFF``) disables adding architectures.
+This is intended to support packagers and rare cases where full control
+over the passed flags is required.
+
+This property is initialized by the value of the :variable:`CMAKE_HIP_ARCHITECTURES`
+variable if it is set when a target is created.
+
+The HIP compilation model has two modes: whole and separable. Whole compilation
+generates device code at compile time. Separable compilation generates device
+code at link time. Therefore the ``HIP_ARCHITECTURES`` target property should
+be set on targets that compile or link with any HIP sources.
+
+Examples
+^^^^^^^^
+
+.. code-block:: cmake
+
+ set_property(TARGET tgt PROPERTY HIP_ARCHITECTURES gfx801 gfx900)
+
+Generates code for both ``gfx801`` and ``gfx900``.
diff --git a/Help/prop_tgt/IMPORTED_OBJECTS.rst b/Help/prop_tgt/IMPORTED_OBJECTS.rst
index f3577eb99..d71c21999 100644
--- a/Help/prop_tgt/IMPORTED_OBJECTS.rst
+++ b/Help/prop_tgt/IMPORTED_OBJECTS.rst
@@ -68,26 +68,24 @@ architecture:
# /path/to/somewhere/objects-iphonesimulator/x86_64/func.o
In some cases, you may want to have configuration-specific object files
-as well. The :variable:`CMAKE_CFG_INTDIR` variable can be a convenient
-way of capturing this in combination with the SDK:
+as well. The ``$(CONFIGURATION)`` Xcode variable is often used for this and
+can be used in conjunction with the others mentioned above:
.. code-block:: cmake
add_library(someObjs OBJECT IMPORTED)
set_property(TARGET someObjs PROPERTY IMPORTED_OBJECTS
- "/path/to/somewhere/${CMAKE_CFG_INTDIR}/$(CURRENT_ARCH)/func.o"
+ "/path/to/somewhere/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/$(CURRENT_ARCH)/func.o"
)
# Example paths:
# /path/to/somewhere/Release-iphoneos/arm64/func.o
# /path/to/somewhere/Debug-iphonesimulator/x86_64/func.o
-When any Xcode variable or :variable:`CMAKE_CFG_INTDIR` is used, CMake is
-not able to fully evaluate the path(s) at configure time. One consequence
-of this is that the configuration-specific
-:prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` properties cannot be used, since
-CMake cannot determine whether an object file exists at a particular
-``<CONFIG>`` location. The ``IMPORTED_OBJECTS`` property must be used for
-these situations and the configuration-specific aspects of the path must be
-handled by using :variable:`CMAKE_CFG_INTDIR` or with another Xcode variable
-``$(CONFIGURATION)``.
+When any Xcode variable is used, CMake is not able to fully evaluate the
+path(s) at configure time. One consequence of this is that the
+configuration-specific :prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` properties cannot
+be used, since CMake cannot determine whether an object file exists at a
+particular ``<CONFIG>`` location. The ``IMPORTED_OBJECTS`` property must be
+used for these situations and the configuration-specific aspects of the path
+should be handled by the ``$(CONFIGURATION)`` Xcode variable.
diff --git a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst
index 16be3cd1b..cba8ac98c 100644
--- a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst
+++ b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst
@@ -4,7 +4,7 @@
.. versionadded:: 3.4
This property is implemented only when ``<LANG>`` is ``C``, ``CXX``,
-``Fortran``, ``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``.
+``Fortran``, ``HIP``, ``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``.
Specify a :ref:`semicolon-separated list <CMake Language Lists>` containing a command line
for a compiler launching tool. The :ref:`Makefile Generators` and the
diff --git a/Help/prop_tgt/LANG_LINKER_LAUNCHER.rst b/Help/prop_tgt/LANG_LINKER_LAUNCHER.rst
new file mode 100644
index 000000000..f6ca5ad43
--- /dev/null
+++ b/Help/prop_tgt/LANG_LINKER_LAUNCHER.rst
@@ -0,0 +1,16 @@
+<LANG>_LINKER_LAUNCHER
+----------------------
+
+.. versionadded:: 3.21
+
+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 a linker launching tool. The :ref:`Makefile Generators` and the
+:generator:`Ninja` generator will run this tool and pass the linker and its
+arguments to the tool. This is useful for tools such as static analyzers.
+
+This property is initialized by the value of the
+:variable:`CMAKE_<LANG>_LINKER_LAUNCHER` variable if it is set when a target is
+created.
diff --git a/Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst b/Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst
index 5c6778d24..dc2dc9e32 100644
--- a/Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst
+++ b/Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst
@@ -10,5 +10,6 @@ to re-link this target. Logical target-level dependencies will not be
affected so the linked shared libraries will still be brought up to
date before this target is built.
-This property is initialized by the value of the variable
-CMAKE_LINK_DEPENDS_NO_SHARED if it is set when a target is created.
+This property is initialized by the value of the
+:variable:`CMAKE_LINK_DEPENDS_NO_SHARED` variable if it is set when a
+target is created.
diff --git a/Help/prop_tgt/LINK_OPTIONS.rst b/Help/prop_tgt/LINK_OPTIONS.rst
index 8c0dfc426..27eadf92d 100644
--- a/Help/prop_tgt/LINK_OPTIONS.rst
+++ b/Help/prop_tgt/LINK_OPTIONS.rst
@@ -28,3 +28,9 @@ for more on defining buildsystem properties.
.. note::
This property must be used in preference to :prop_tgt:`LINK_FLAGS` property.
+
+.. include:: ../command/DEVICE_LINK_OPTIONS.txt
+
+.. include:: ../command/OPTIONS_SHELL.txt
+
+.. include:: ../command/LINK_OPTIONS_LINKER.txt
diff --git a/Help/prop_tgt/OBJCXX_STANDARD.rst b/Help/prop_tgt/OBJCXX_STANDARD.rst
index 96088af96..654e6877d 100644
--- a/Help/prop_tgt/OBJCXX_STANDARD.rst
+++ b/Help/prop_tgt/OBJCXX_STANDARD.rst
@@ -9,7 +9,27 @@ This property specifies the ObjC++ standard whose features are requested
to build this target. For some compilers, this results in adding a
flag such as ``-std=gnu++11`` to the compile line.
-Supported values are ``98``, ``11``, ``14``, ``17``, ``20``, ``23``.
+Supported values are:
+
+``98``
+ Objective C++98
+
+``11``
+ Objective C++11
+
+``14``
+ Objective C++14
+
+``17``
+ Objective C++17
+
+``20``
+ Objective C++20
+
+``23``
+ .. versionadded:: 3.20
+
+ Objective C++23
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
diff --git a/Help/prop_tgt/OBJC_STANDARD.rst b/Help/prop_tgt/OBJC_STANDARD.rst
index 2143ff92d..2d27bcf00 100644
--- a/Help/prop_tgt/OBJC_STANDARD.rst
+++ b/Help/prop_tgt/OBJC_STANDARD.rst
@@ -9,7 +9,16 @@ This property specifies the OBJC standard whose features are requested
to build this target. For some compilers, this results in adding a
flag such as ``-std=gnu11`` to the compile line.
-Supported values are ``90``, ``99`` and ``11``.
+Supported values are:
+
+``90``
+ Objective C89/C90
+
+``99``
+ Objective C99
+
+``11``
+ Objective C11
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
diff --git a/Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst b/Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst
index 2f4a3baab..f5d943723 100644
--- a/Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst
+++ b/Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst
@@ -20,3 +20,5 @@ for more on defining buildsystem properties.
This property must be used in preference to :prop_tgt:`STATIC_LIBRARY_FLAGS`
property.
+
+.. include:: ../command/OPTIONS_SHELL.txt
diff --git a/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst b/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst
index a6484f2fd..619377a11 100644
--- a/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst
+++ b/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst
@@ -9,4 +9,4 @@ If the target contains Swift source files, this specifies the directory in which
the modules will be placed. When this property is not set, the modules will be
placed in the build directory corresponding to the target's source directory.
If the variable :variable:`CMAKE_Swift_MODULE_DIRECTORY` is set when a target is
-created its value is used to initialise this property.
+created its value is used to initialize this property.
diff --git a/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst b/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst
index 2c95e027c..d288dd3b4 100644
--- a/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst
+++ b/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst
@@ -50,6 +50,6 @@ be used to avoid that with code like the following:
return MY_UNITY_ID::i;
}
-The pseudononymous namespace is used within a truly anonymous namespace.
+The pseudonymous namespace is used within a truly anonymous namespace.
On many platforms, this maintains the invariant that the symbols within
do not get external linkage when performing a unity build.
diff --git a/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst
index 7b6812678..2a4d66672 100644
--- a/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst
+++ b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst
@@ -6,3 +6,8 @@ XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY
Tell the :generator:`Xcode` generator to perform code signing for all the
frameworks and libraries that are embedded using the
:prop_tgt:`XCODE_EMBED_FRAMEWORKS <XCODE_EMBED_<type>>` property.
+
+.. versionadded:: 3.21
+
+This property was generalized to other types of embedded items. See
+:prop_tgt:`XCODE_EMBED_<type>_CODE_SIGN_ON_COPY` for the more general form.
diff --git a/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst
index 29f8c5c03..04daa8559 100644
--- a/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst
+++ b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst
@@ -6,3 +6,9 @@ XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY
Tell the :generator:`Xcode` generator to remove headers from all the
frameworks that are embedded using the
:prop_tgt:`XCODE_EMBED_FRAMEWORKS <XCODE_EMBED_<type>>` property.
+
+.. versionadded:: 3.21
+
+This property was generalized to other types of embedded items. See
+:prop_tgt:`XCODE_EMBED_<type>_REMOVE_HEADERS_ON_COPY` for the more
+general form.
diff --git a/Help/prop_tgt/XCODE_EMBED_type.rst b/Help/prop_tgt/XCODE_EMBED_type.rst
index 90c5bc787..a1af56f12 100644
--- a/Help/prop_tgt/XCODE_EMBED_type.rst
+++ b/Help/prop_tgt/XCODE_EMBED_type.rst
@@ -5,10 +5,20 @@ XCODE_EMBED_<type>
Tell the :generator:`Xcode` generator to embed the specified list of items into
the target bundle. ``<type>`` specifies the embed build phase to use.
+See the Xcode documentation for the base location of each ``<type>``.
+
+The supported values for ``<type>`` are:
+
+``FRAMEWORKS``
+ The specified items will be added to the ``Embed Frameworks`` build phase.
+ The items can be CMake target names or paths to frameworks or libraries.
+
+``APP_EXTENSIONS``
+ .. versionadded:: 3.21
+
+ The specified items will be added to the ``Embed App Extensions`` build phase.
+ They must be CMake target names.
-Currently, the only supported value for ``<type>`` is ``FRAMEWORKS``.
-The specified items will be added to the ``Embed Frameworks`` build phase.
-The items can be CMake target names or paths to frameworks or libraries.
See also :prop_tgt:`XCODE_EMBED_<type>_PATH`,
-:prop_tgt:`XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY` and
-:prop_tgt:`XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY`.
+:prop_tgt:`XCODE_EMBED_<type>_REMOVE_HEADERS_ON_COPY` and
+:prop_tgt:`XCODE_EMBED_<type>_CODE_SIGN_ON_COPY`.
diff --git a/Help/prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY.rst b/Help/prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY.rst
new file mode 100644
index 000000000..7ec03857b
--- /dev/null
+++ b/Help/prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY.rst
@@ -0,0 +1,18 @@
+XCODE_EMBED_<type>_CODE_SIGN_ON_COPY
+------------------------------------
+
+.. versionadded:: 3.20
+
+Boolean property used only by the :generator:`Xcode` generator. It specifies
+whether to perform code signing for the items that are embedded using the
+:prop_tgt:`XCODE_EMBED_<type>` property.
+
+The supported values for ``<type>`` are:
+
+``FRAMEWORKS``
+
+``APP_EXTENSIONS``
+ .. versionadded:: 3.21
+
+If a ``XCODE_EMBED_<type>_CODE_SIGN_ON_COPY`` property is not defined on the
+target, no code signing on copy will be performed for that ``<type>``.
diff --git a/Help/prop_tgt/XCODE_EMBED_type_PATH.rst b/Help/prop_tgt/XCODE_EMBED_type_PATH.rst
index 887cf5721..a6f980dcc 100644
--- a/Help/prop_tgt/XCODE_EMBED_type_PATH.rst
+++ b/Help/prop_tgt/XCODE_EMBED_type_PATH.rst
@@ -3,7 +3,16 @@ XCODE_EMBED_<type>_PATH
.. versionadded:: 3.20
-Tell the :generator:`Xcode` generator the relative path to use when embedding
-the items specified by :prop_tgt:`XCODE_EMBED_<type>`. The path is relative
+This property is used only by the :generator:`Xcode` generator. When defined,
+it specifies the relative path to use when embedding the items specified by
+:prop_tgt:`XCODE_EMBED_<type>`. The path is relative
to the base location of the ``Embed XXX`` build phase associated with
+``<type>``. See the Xcode documentation for the base location of each
``<type>``.
+
+The supported values for ``<type>`` are:
+
+``FRAMEWORKS``
+
+``APP_EXTENSIONS``
+ .. versionadded:: 3.21
diff --git a/Help/prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY.rst b/Help/prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY.rst
new file mode 100644
index 000000000..75c8eae13
--- /dev/null
+++ b/Help/prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY.rst
@@ -0,0 +1,20 @@
+XCODE_EMBED_<type>_REMOVE_HEADERS_ON_COPY
+-----------------------------------------
+
+.. versionadded:: 3.20
+
+Boolean property used only by the :generator:`Xcode` generator. It specifies
+whether to remove headers from all the frameworks that are embedded using the
+:prop_tgt:`XCODE_EMBED_<type>` property.
+
+The supported values for ``<type>`` are:
+
+``FRAMEWORKS``
+ If the ``XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY`` property is not
+ defined, headers will not be removed on copy by default.
+
+``APP_EXTENSIONS``
+ .. versionadded:: 3.21
+
+ If the ``XCODE_EMBED_APP_EXTENSIONS_REMOVE_HEADERS_ON_COPY`` property is not
+ defined, headers WILL be removed on copy by default.
diff --git a/Help/release/3.15.rst b/Help/release/3.15.rst
index e68e7d38b..6b1a8007a 100644
--- a/Help/release/3.15.rst
+++ b/Help/release/3.15.rst
@@ -40,7 +40,7 @@ Languages
customize the Swift module name.
* The :prop_sf:`Swift_DIAGNOSTICS_FILE` source property was added to
- indicate where to write the serialised Swift diagnostics.
+ indicate where to write the serialized Swift diagnostics.
The Swift support is experimental, not considered stable, and may change
in future releases of CMake.
diff --git a/Help/release/3.16.rst b/Help/release/3.16.rst
index 84d96cdc8..28273a762 100644
--- a/Help/release/3.16.rst
+++ b/Help/release/3.16.rst
@@ -233,7 +233,7 @@ Deprecated and Removed Features
instead.
* The :module:`GetPrerequisites` module has been deprecated, as it has been
- superceded by :command:`file(GET_RUNTIME_DEPENDENCIES)`.
+ superseded by :command:`file(GET_RUNTIME_DEPENDENCIES)`.
* The ``CPACK_INSTALL_SCRIPT`` variable has been deprecated in favor of the
new, more accurately named :variable:`CPACK_INSTALL_SCRIPTS` variable.
diff --git a/Help/release/3.20.rst b/Help/release/3.20.rst
index 42e95beec..da27174d7 100644
--- a/Help/release/3.20.rst
+++ b/Help/release/3.20.rst
@@ -363,8 +363,8 @@ Changes made since CMake 3.20.0 include the following.
The oneAPI 2021.2 Fortran compiler defines the proper identification
macro and so is identified as ``IntelLLVM`` by all CMake 3.20 versions.
-3.20.3, 3.20.4, 3.20.5, 3.20.6
-------------------------------
+3.20.3, 3.20.4, 3.20.5
+----------------------
These versions made no changes to documented features or interfaces.
Some implementation updates were made to support ecosystem changes
diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst
new file mode 100644
index 000000000..204880b7b
--- /dev/null
+++ b/Help/release/3.21.rst
@@ -0,0 +1,295 @@
+CMake 3.21 Release Notes
+************************
+
+.. only:: html
+
+ .. contents::
+
+Changes made since CMake 3.20 include the following.
+
+New Features
+============
+
+Presets
+-------
+
+* :manual:`cmake-presets(7)` gained support for specifying the install prefix
+ in a configure preset.
+
+* :manual:`cmake-presets(7)` gained support for conditional enabling of presets.
+
+* :manual:`cmake-presets(7)` gained support for a ``${hostSystemName}`` macro.
+
+* :manual:`cmake-presets(7)` gained support for omitting the ``generator`` and
+ ``binaryDir`` fields.
+
+Generators
+----------
+
+* The :generator:`Visual Studio 17 2022` generator was added. This is
+ experimental and based on "Visual Studio 2022 Preview 1.1" because this
+ version of VS has not been released.
+
+* The :ref:`Makefile Generators` and the :generator:`Ninja` generator
+ learned to add linker launcher tools along with the linker for ``C``,
+ ``CXX``, ``OBJC``, and ``OBJCXX`` languages.
+ See the :variable:`CMAKE_<LANG>_LINKER_LAUNCHER` variable
+ and :prop_tgt:`<LANG>_LINKER_LAUNCHER` target property for details.
+
+Languages
+---------
+
+* CMake learned to support ``HIP`` as a first-class language that can be
+ enabled via the :command:`project` and :command:`enable_language` commands.
+
+* :prop_tgt:`C_STANDARD`, :prop_tgt:`OBJC_STANDARD`, and the
+ :manual:`Compile Features <cmake-compile-features(7)>` functionality gained
+ support for C17 and C23.
+
+* Source file extensions ``.ixx`` and ``.cppm`` are now treated as C++.
+
+Command-Line
+------------
+
+* :manual:`cmake(1)` gained the ``--install-prefix <dir>``
+ command-line option to specify the location of the install prefix.
+
+* :manual:`cmake(1)` gained the ``--toolchain <path/to/file>``
+ 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`.
+
+* Messages printed to a terminal now may be colored by message type.
+
+Compilers
+---------
+
+* The Fujitsu compiler is now supported using compiler id ``Fujitsu``
+ in traditional (``Trad``) mode, and compiler id ``FujitsuClang``
+ in ``Clang`` mode.
+
+Platforms
+---------
+
+* CMake now supports the MSYS runtime environment, much like CYGWIN.
+
+File-Based API
+--------------
+
+* The :manual:`cmake-file-api(7)` "codemodel" version 2 ``version`` field
+ has been updated to 2.3.
+
+* The :manual:`cmake-file-api(7)` "codemodel" version 2 gained a
+ new "directory" object containing directory-level information.
+ This includes a list of installers generated by the :command:`install`
+ command.
+
+Commands
+--------
+
+* The :command:`add_custom_command` command ``DEPFILE`` option:
+
+ * may now use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`,
+
+ * is now supported by :ref:`Visual Studio Generators` for VS 2012
+ and above, and
+
+ * is now supported by the :generator:`Xcode` generator.
+
+* The :command:`add_custom_command(TARGET)` command
+ (for :ref:`Build Events <add_custom_command(TARGET)>`)
+ gained support for resolving target-dependent generator expressions.
+
+* The :command:`build_command` command gained a ``PARALLEL_LEVEL`` option.
+
+* The :command:`file(COPY_FILE)` command was added to copy a single file.
+
+* The :command:`file(GET_RUNTIME_DEPENDENCIES)` command gained new
+ ``POST_INCLUDE_FILES`` and ``POST_EXCLUDE_FILES`` arguments.
+
+* The :command:`file(REAL_PATH)` command gained the option ``EXPAND_TILDE`` to
+ replace any leading tilde with the path to the user's home directory.
+
+* The :command:`file(RENAME)` command learned to optionally capture
+ failure in a result variable. It also gained a ``NO_REPLACE``
+ option to fail if the destination exists.
+
+* The :command:`install` command gained a new ``IMPORTED_RUNTIME_ARTIFACTS``
+ mode, which can be used to install the runtime artifacts of imported targets.
+
+* The :command:`install` command gained a new ``RUNTIME_DEPENDENCY_SET`` mode,
+ which can be used to install runtime dependencies using
+ :command:`file(GET_RUNTIME_DEPENDENCIES)`.
+
+* The :command:`install(TARGETS)` command gained new ``RUNTIME_DEPENDENCIES``
+ and ``RUNTIME_DEPENDENCY_SET`` arguments, which can be used to install
+ runtime dependencies using :command:`file(GET_RUNTIME_DEPENDENCIES)`.
+
+* The :command:`install(SCRIPT|CODE)` command
+ supports a new option ``ALL_COMPONENTS`` which allows
+ the corresponding code to run for every component of
+ a per component installation.
+
+* The :command:`project` command now sets variables
+ :variable:`PROJECT_IS_TOP_LEVEL` and :variable:`<PROJECT-NAME>_IS_TOP_LEVEL`
+ to indicate whether it was called in a top-level ``CMakeLists.txt`` file.
+
+Variables
+---------
+
+* The :envvar:`CMAKE_TOOLCHAIN_FILE` environment variable was added to
+ provide a default value for the :variable:`CMAKE_TOOLCHAIN_FILE` variable.
+
+Properties
+----------
+
+* The :prop_dir:`IMPORTED_TARGETS` directory property was added to
+ get a list of :ref:`Imported Targets` created in the current
+ directory.
+
+* The :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS <XCODE_EMBED_<type>>` target property
+ was added to tell the :generator:`Xcode` generator to embed app extensions
+ such as iMessage sticker packs.
+ Aspects of the embedding can be customized with the
+ :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_PATH <XCODE_EMBED_<type>>`,
+ :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_CODE_SIGN_ON_COPY <XCODE_EMBED_<type>_CODE_SIGN_ON_COPY>` and
+ :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_REMOVE_HEADERS_ON_COPY <XCODE_EMBED_<type>_REMOVE_HEADERS_ON_COPY>`
+ properties.
+
+Modules
+-------
+
+* The :module:`FindBLAS` and :module:`FindLAPACK` modules learned to support
+ the serial ``Fujitsu_SSL2`` and parallel ``Fujitsu_SSL2BLAMP`` libraries.
+
+* The :module:`FindDevIL` module now provides imported targets.
+
+* The :module:`FindIconv` module now has version support.
+
+* The :module:`FindIntl` module now has version support.
+
+* The :module:`FindMPI` module learned to support ``Fujitsu`` and
+ ``FujitsuClang`` in both host and cross compiling modes.
+
+* The :module:`FindMsys` module was added to find MSYS installations.
+ Like :module:`FindCygwin`, it is used automatically by some other
+ find modules to locate UNIX-style tools on Windows.
+
+* The :module:`FindOpenMP` module learned to support ``Fujitsu`` and
+ ``FujitsuClang``.
+
+* The :module:`FindVulkan` module gained imported targets
+ ``Vulkan::Headers`` and ``Vulkan::glslangValidator``.
+
+* The :module:`UseJava` module command ``add_jar`` gained a ``RESOURCES``
+ option to allow explicit naming of resources with non-optional namespace.
+
+* The :module:`UseSWIG` module use now standard library naming conventions
+ for the ``CSharp`` language. See policy :policy:`CMP0122`.
+
+* The :module:`UseSWIG` module now supports using the ``swig`` tool to
+ generate implicit dependencies with the :generator:`Xcode` generator.
+
+Generator Expressions
+---------------------
+
+* A new :genex:`TARGET_RUNTIME_DLLS` generator expression was added.
+
+CTest
+-----
+
+* :manual:`ctest(1)` gained documentation for its ability to capture
+ :ref:`Additional Test Measurements`.
+
+* :manual:`ctest(1)` learned to recognize files attached to a test at run time.
+ Previously it was only possible to attach files to tests at configure time
+ by using the :prop_test:`ATTACHED_FILES` or
+ :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.
+
+* The :command:`ctest_build` command gained a ``PARALLEL_LEVEL`` option.
+
+CPack
+-----
+
+* The :cpack_gen:`CPack DragNDrop Generator` gained option
+ :variable:`CPACK_DMG_FILESYSTEM` to control the ``.dmg`` filesystem.
+
+* The :cpack_gen:`CPack IFW Generator` now supports hyphens in names
+ given to :command:`cpack_ifw_configure_component` or
+ :command:`cpack_ifw_configure_component_group` as ``DEPENDS`` or
+ ``DEPENDENCIES`` arguments. This requires QtIFW 3.1 or later.
+
+* The :cpack_gen:`CPack NSIS Generator` gained a new
+ :variable:`CPACK_NSIS_EXECUTABLE` variable to specify the ``makensis``
+ executable to use instead of the default one.
+
+* The :variable:`CPACK_CUSTOM_INSTALL_VARIABLES` variable was added to set
+ variables in ``cmake_install.cmake`` script invocations made by CPack.
+
+Deprecated and Removed Features
+===============================
+
+* Undocumented :variable:`CMAKE_SYSTEM_NAME` version-stripping behavior has
+ been removed entirely. If it is set by a ``-D`` flag or by a
+ :manual:`toolchain file <cmake-toolchains(7)>`, it is left unaltered,
+ even if it still contains a version number.
+ Similar :variable:`CMAKE_HOST_SYSTEM_NAME` version-stripping behavior,
+ also undocumented, has been moved earlier, before :command:`project` or
+ :command:`enable_language` is called.
+
+* ``ARMClang`` cpu/arch compile and link flags are no longer added
+ automatically based on the :variable:`CMAKE_SYSTEM_PROCESSOR`
+ variable or the undocumented ``CMAKE_SYSTEM_ARCH`` variable.
+ They must be specified explicitly. See policy :policy:`CMP0123`.
+
+Other Changes
+=============
+
+* The :command:`find_file`, :command:`find_path`, :command:`find_program`,
+ and :command:`find_library` commands handle cache variables in the same way
+ regardless how they are defined. See policy :policy:`CMP0125` for details.
+
+* The :command:`find_file`, :command:`find_path`, :command:`find_program`,
+ and :command:`find_library` commands gained the option ``NO_CACHE`` to store
+ find result in normal variable.
+
+* The :command:`foreach` command now isolates loop variables in the loop scope.
+ See policy :policy:`CMP0124` for details.
+
+* The :command:`list` command's ``GET``, ``INSERT``, ``SUBLIST``, and
+ ``REMOVE_AT`` subcommands now error with invalid (i.e., non-integer) values
+ are given as any of their index arguments based on the setting of policy
+ :policy:`CMP0121`.
+
+* The :command:`set(CACHE)` command no longer removes a normal variable
+ of the same name, if any. See policy :policy:`CMP0126`.
+
+* :command:`target_link_libraries` calls referencing object libraries
+ via the :genex:`TARGET_OBJECTS` generator expression now place the
+ object files before all libraries on the link line, regardless of
+ their specified order. See documentation on
+ :ref:`Linking Object Libraries via \$\<TARGET_OBJECTS\>` for details.
+
+* The :ref:`Ninja Generators` now pass source files and include directories
+ to the compiler using absolute paths. This makes diagnostic messages and
+ debug symbols more consistent, and matches the :ref:`Makefile Generators`.
+
+* The :generator:`NMake Makefiles` generator now encodes the generated
+ makefiles as UTF-8 with a BOM when using ``nmake`` from VS 9 or above.
+
+* The :ref:`Visual Studio Generators` for VS 2010 and above now place
+ per-source preprocessor definitions after target-wide preprocssor
+ definitions. This makes VS consistent with the :ref:`Ninja Generators`
+ and the :ref:`Makefile Generators`.
+
+* The precompiled binaries provided on
+ `cmake.org <https://cmake.org/download/>`_ now support
+ ``liblzma`` multi-threading. See the :variable:`CPACK_THREADS` and
+ :variable:`CPACK_ARCHIVE_THREADS` variables.
diff --git a/Help/release/3.6.rst b/Help/release/3.6.rst
index f0add07ff..b798f0d6e 100644
--- a/Help/release/3.6.rst
+++ b/Help/release/3.6.rst
@@ -170,7 +170,7 @@ CPack
is used for dependency auto detection.
* The :cpack_gen:`CPack DEB Generator` learned how to generate
- ``DEBIAN/shlibs`` contorl file when package contains shared libraries.
+ ``DEBIAN/shlibs`` control file when package contains shared libraries.
* The :cpack_gen:`CPack DEB Generator` learned how to generate
``DEBIAN/postinst`` and ``DEBIAN/postrm`` files if the package installs
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 95b41fb63..75667e54f 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -13,6 +13,7 @@ Releases
.. toctree::
:maxdepth: 1
+ 3.21 <3.21>
3.20 <3.20>
3.19 <3.19>
3.18 <3.18>
diff --git a/Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst b/Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst
index 6c0c61b11..0b0b11414 100644
--- a/Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst
+++ b/Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst
@@ -8,7 +8,7 @@ Switch between strict and relaxed automoc mode.
By default, :prop_tgt:`AUTOMOC` behaves exactly as described in the
documentation of the :prop_tgt:`AUTOMOC` target property. When set to
``TRUE``, it accepts more input and tries to find the correct input file for
-``moc`` even if it differs from the documented behaviour. In this mode it
+``moc`` even if it differs from the documented behavior. In this mode it
e.g. also checks whether a header file is intended to be processed by moc
when a ``"foo.moc"`` file has been included.
diff --git a/Help/variable/CMAKE_CFG_INTDIR.rst b/Help/variable/CMAKE_CFG_INTDIR.rst
index 842654ec5..43668eaac 100644
--- a/Help/variable/CMAKE_CFG_INTDIR.rst
+++ b/Help/variable/CMAKE_CFG_INTDIR.rst
@@ -1,6 +1,12 @@
CMAKE_CFG_INTDIR
----------------
+.. deprecated:: 3.21
+
+ This variable has poor support on :generator:`Ninja Multi-Config`, and
+ predates the existence of the :genex:`$<CONFIG>` generator expression. Use
+ ``$<CONFIG>`` instead.
+
Build-time reference to per-configuration output subdirectory.
For native build systems supporting multiple configurations in the
@@ -19,11 +25,6 @@ Example values:
. = Ninja
${CONFIGURATION} = Ninja Multi-Config
-Note that this variable only has limited support on
-:generator:`Ninja Multi-Config`. It is recommended that you use the
-``$<CONFIG>`` :manual:`generator expression <cmake-generator-expressions(7)>`
-instead.
-
Since these values are evaluated by the native build system, this
variable is suitable only for use in command lines that will be
evaluated at build time. Example of intended usage:
diff --git a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst
index 34e99ebf7..8fcc79869 100644
--- a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst
+++ b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst
@@ -6,5 +6,7 @@ Specifies the available build types on multi-config generators.
This specifies what build types (configurations) will be available
such as ``Debug``, ``Release``, ``RelWithDebInfo`` etc. This has reasonable
defaults on most platforms, but can be extended to provide other build
-types. See also :variable:`CMAKE_BUILD_TYPE` for details of managing
-configuration data, and :variable:`CMAKE_CFG_INTDIR`.
+types.
+
+See :variable:`CMAKE_BUILD_TYPE` for specifying the configuration with
+single-config generators.
diff --git a/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst b/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst
index d5fcb7dbf..9817b1a12 100644
--- a/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst
+++ b/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst
@@ -23,3 +23,7 @@ is read-only and changes to it are undefined behavior.
:variable:`CMAKE_CUDA_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` is ``NVIDIA``,
it does not make sense to set ``CMAKE_CUDA_HOST_COMPILER`` without also
setting ``CMAKE_CUDA_COMPILER`` to NVCC.
+
+.. note::
+
+ Ignored when using :ref:`Visual Studio Generators`.
diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst
index 53ad2f3e7..45f2d3236 100644
--- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst
+++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst
@@ -63,3 +63,27 @@ Supported pairs are:
Specify an alternative ``VCTargetsPath`` value for Visual Studio
project files. This allows use of VS platform extension configuration
files (``.props`` and ``.targets``) that are not installed with VS.
+
+Visual Studio Toolset Customization
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**These are unstable interfaces with no compatibility guarantees**
+because they hook into undocumented internal CMake implementation details.
+Institutions may use these to internally maintain support for non-public
+Visual Studio platforms and toolsets, but must accept responsibility to
+make updates as changes are made to CMake.
+
+Additional ``key=value`` pairs are available:
+
+``customFlagTableDir=<path>``
+ .. versionadded:: 3.21
+
+ Specify the absolute path to a directory from which to load custom
+ flag tables stored as JSON documents with file names of the form
+ ``<platform>_<toolset>_<tool>.json`` or ``<platform>_<tool>.json``,
+ where ``<platform>`` is the :variable:`CMAKE_VS_PLATFORM_NAME`,
+ ``<toolset>`` is the :variable:`CMAKE_VS_PLATFORM_TOOLSET`,
+ and ``<tool>`` is the tool for which the flag table is meant.
+ **This naming pattern is an internal CMake implementation detail.**
+ The ``<tool>`` names are undocumented. The format of the ``.json``
+ flag table files is undocumented.
diff --git a/Help/variable/CMAKE_HIP_ARCHITECTURES.rst b/Help/variable/CMAKE_HIP_ARCHITECTURES.rst
new file mode 100644
index 000000000..0cf020136
--- /dev/null
+++ b/Help/variable/CMAKE_HIP_ARCHITECTURES.rst
@@ -0,0 +1,11 @@
+CMAKE_HIP_ARCHITECTURES
+-----------------------
+
+.. versionadded:: 3.21
+
+Default value for :prop_tgt:`HIP_ARCHITECTURES` property of targets.
+
+This is initialized to the default architecture chosen by the compiler.
+
+This variable is used to initialize the :prop_tgt:`HIP_ARCHITECTURES` property
+on all targets. See the target property for additional information.
diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
index 89d9e2757..f23b7a214 100644
--- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
@@ -19,6 +19,8 @@ include:
Cray = Cray Compiler (cray.com)
Embarcadero, Borland = Embarcadero (embarcadero.com)
Flang = Flang LLVM Fortran Compiler
+ 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)
@@ -32,6 +34,7 @@ include:
OpenWatcom = Open Watcom (openwatcom.org)
PGI = The Portland Group (pgroup.com)
PathScale = PathScale (pathscale.com)
+ ROCMClang = ROCm Toolkit Clang-based Compiler (rocmdocs.amd.com)
SDCC = Small Device C Compiler (sdcc.sourceforge.net)
SunPro = Oracle Solaris Studio (oracle.com)
TI = Texas Instruments (ti.com)
diff --git a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst
index 89fd7bcda..f16e59446 100644
--- a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst
@@ -6,7 +6,7 @@ CMAKE_<LANG>_COMPILER_LAUNCHER
Default value for :prop_tgt:`<LANG>_COMPILER_LAUNCHER` target property.
This variable is used to initialize the property on each target as it is
created. This is done only when ``<LANG>`` is ``C``, ``CXX``, ``Fortran``,
-``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``.
+``HIP``, ``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``.
This variable is initialized to the :envvar:`CMAKE_<LANG>_COMPILER_LAUNCHER`
environment variable if it is set.
diff --git a/Help/variable/CMAKE_LANG_FLAGS.rst b/Help/variable/CMAKE_LANG_FLAGS.rst
index 14b2694ef..2784397ac 100644
--- a/Help/variable/CMAKE_LANG_FLAGS.rst
+++ b/Help/variable/CMAKE_LANG_FLAGS.rst
@@ -15,3 +15,11 @@ 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.
+
+This value is a command-line string fragment. Therefore, multiple options
+should be separated by spaces, and options with spaces should be quoted.
+
+The flags in this variable will be passed to the compiler before those
+in the per-configuration :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` variant,
+and before flags added by the :command:`add_compile_options` or
+:command:`target_compile_options` commands.
diff --git a/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst b/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst
index 628b62ba2..f0900fdc8 100644
--- a/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst
+++ b/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst
@@ -1,6 +1,9 @@
CMAKE_<LANG>_FLAGS_<CONFIG>
---------------------------
-.. versionadded:: 3.11
-
Flags for language ``<LANG>`` when building for the ``<CONFIG>`` configuration.
+
+The flags in this variable will be passed to the compiler after those
+in the :variable:`CMAKE_<LANG>_FLAGS` variable, but before flags added
+by the :command:`add_compile_options` or :command:`target_compile_options`
+commands.
diff --git a/Help/variable/CMAKE_LANG_FLAGS_INIT.rst b/Help/variable/CMAKE_LANG_FLAGS_INIT.rst
index 67ff2cb3e..ca13a29a0 100644
--- a/Help/variable/CMAKE_LANG_FLAGS_INIT.rst
+++ b/Help/variable/CMAKE_LANG_FLAGS_INIT.rst
@@ -12,6 +12,8 @@ the contents of a ``xxxFLAGS`` environment variable will be prepended,
where ``xxx`` will be language-specific but not necessarily the same as
``<LANG>`` (e.g. :envvar:`CXXFLAGS` for ``CXX``, :envvar:`FFLAGS` for
``Fortran``, and so on).
+This value is a command-line string fragment. Therefore, multiple options
+should be separated by spaces, and options with spaces should be quoted.
See also the configuration-specific
:variable:`CMAKE_<LANG>_FLAGS_<CONFIG>_INIT` variable.
diff --git a/Help/variable/CMAKE_LANG_LINKER_LAUNCHER.rst b/Help/variable/CMAKE_LANG_LINKER_LAUNCHER.rst
new file mode 100644
index 000000000..b76b9391b
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_LINKER_LAUNCHER.rst
@@ -0,0 +1,11 @@
+CMAKE_<LANG>_LINKER_LAUNCHER
+----------------------------
+
+.. versionadded:: 3.21
+
+Default value for :prop_tgt:`<LANG>_LINKER_LAUNCHER` target property. This
+variable is used to initialize the property on each target as it is created.
+This is done only when ``<LANG>`` is ``C``, ``CXX``, ``OBJC``, or ``OBJCXX``.
+
+This variable is initialized to the :envvar:`CMAKE_<LANG>_LINKER_LAUNCHER`
+environment variable if it is set.
diff --git a/Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst b/Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst
index f466468d8..8d6b53369 100644
--- a/Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst
+++ b/Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst
@@ -2,4 +2,5 @@ CMAKE_MINIMUM_REQUIRED_VERSION
------------------------------
The ``<min>`` version of CMake given to the most recent call to the
-:command:`cmake_minimum_required(VERSION)` command.
+:command:`cmake_minimum_required(VERSION)` command in the current
+variable scope or any parent variable scope.
diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
index 9f68741a5..b991db2df 100644
--- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
+++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
@@ -29,6 +29,8 @@ warn by default:
policy :policy:`CMP0112`.
* ``CMAKE_POLICY_WARNING_CMP0116`` controls the warning for
policy :policy:`CMP0116`.
+* ``CMAKE_POLICY_WARNING_CMP0126`` controls the warning for
+ policy :policy:`CMP0126`.
This variable should not be set by a project in CMake code. Project
developers running CMake may set this variable in their cache to
diff --git a/Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst b/Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst
index 36949739f..6036c04bb 100644
--- a/Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst
+++ b/Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst
@@ -5,6 +5,6 @@ CMAKE_Swift_MODULE_DIRECTORY
Swift module output directory.
-This variable is used to initialise the :prop_tgt:`Swift_MODULE_DIRECTORY`
+This variable is used to initialize the :prop_tgt:`Swift_MODULE_DIRECTORY`
property on all the targets. See the target property for additional
information.
diff --git a/Help/variable/CMAKE_TLS_VERIFY.rst b/Help/variable/CMAKE_TLS_VERIFY.rst
new file mode 100644
index 000000000..24f8a256a
--- /dev/null
+++ b/Help/variable/CMAKE_TLS_VERIFY.rst
@@ -0,0 +1,17 @@
+CMAKE_TLS_VERIFY
+----------------
+
+Specify the default value for the :command:`file(DOWNLOAD)` and
+:command:`file(UPLOAD)` commands' ``TLS_VERIFY`` options.
+If not set, the default is *off*.
+
+This setting is also used by the :module:`ExternalProject` module
+for internal calls to :command:`file(DOWNLOAD)`.
+
+TLS verification can help provide confidence that one is connecting
+to the desired server. When downloading known content, one should
+also use file hashes to verify it.
+
+.. code-block:: cmake
+
+ set(CMAKE_TLS_VERIFY TRUE)
diff --git a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst
index 168ee74c7..ff8d59a69 100644
--- a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst
+++ b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst
@@ -7,3 +7,9 @@ This variable is specified on the command line when cross-compiling with CMake.
It is the path to a file which is read early in the CMake run and which
specifies locations for compilers and toolchain utilities, and other target
platform and compiler related information.
+
+Relative paths are allowed and are interpreted first as relative to the
+build directory, and if not found, relative to the source directory.
+
+This is initialized by the :envvar:`CMAKE_TOOLCHAIN_FILE` environment
+variable if it is set when a new build tree is first created.
diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst
index 74db6b143..a19e7e148 100644
--- a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst
+++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst
@@ -9,10 +9,9 @@ The :ref:`Visual Studio Generators` for VS 2010 and above support using
a standalone (non-installed) NVIDIA CUDA toolkit. The path
may be specified by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of
the form ``cuda=C:\path\to\cuda``. The given directory must at least
-contain a folder ``.\nvcc`` and must provide Visual Studio integration
-files in path ``.\CUDAVisualStudioIntegration\extras\
-visual_studio_integration\MSBuildExtensions\``. One can create a standalone
-CUDA toolkit directory by either opening a installer with 7zip or
-copying the files that are extracted by the running installer.
-The value may be empty if no path to a standalone CUDA Toolkit was
-specified.
+contain the nvcc compiler in path ``.\bin`` and must provide Visual Studio
+integration files in path ``.\extras\visual_studio_integration\
+MSBuildExtensions\``. One can create a standalone CUDA toolkit directory by
+either opening a installer with 7zip or copying the files that are extracted
+by the running installer. The value may be empty if no path to a standalone
+CUDA Toolkit was specified.
diff --git a/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst
new file mode 100644
index 000000000..1c070b8fa
--- /dev/null
+++ b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst
@@ -0,0 +1,44 @@
+CPACK_CUSTOM_INSTALL_VARIABLES
+------------------------------
+
+.. versionadded:: 3.21
+
+CPack variables (set via e.g. ``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,
+each list item will result in a variable of the specified name (``varName``)
+being set to the given ``value``. The ``=`` can be omitted for an empty
+``value``.
+
+``CPACK_CUSTOM_INSTALL_VARIABLES`` allows the packaging installation to be
+influenced by the user or driving script at CPack runtime without having to
+regenerate the install scripts.
+
+Example
+"""""""
+
+.. code-block:: cmake
+
+ install(FILES large.txt DESTINATION data)
+
+ install(CODE [[
+ if(ENABLE_COMPRESSION)
+ # "run-compressor" is a fictional tool that produces
+ # large.txt.xz from large.txt and then removes the input file
+ execute_process(COMMAND run-compressor $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/large.txt)
+ endif()
+ ]])
+
+With the above example snippet, :manual:`cpack <cpack(1)>` will by default
+run the installation script with ``ENABLE_COMPRESSION`` unset, resulting in
+a package containing the uncompressed ``large.txt``. This can be overridden
+when invoking :manual:`cpack <cpack(1)>` like so:
+
+.. code-block:: shell
+
+ cpack -D "CPACK_CUSTOM_INSTALL_VARIABLES=ENABLE_COMPRESSION=TRUE"
+
+The installation script will then run with ``ENABLE_COMPRESSION`` set to
+``TRUE``, resulting in a package containing the compressed ``large.txt.xz``
+instead.
diff --git a/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst b/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst
index 5aeae88a4..9f145c1a2 100644
--- a/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst
+++ b/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst
@@ -5,4 +5,7 @@ When saving a failing test's output, this is the maximum size, in bytes, that
will be collected by the :command:`ctest_test` command. Defaults to 307200
(300 KiB).
+If a test's output contains the literal string "CTEST_FULL_OUTPUT",
+the output will not be truncated and may exceed the maximum size.
+
.. include:: CTEST_CUSTOM_XXX.txt
diff --git a/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst b/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst
index 1fbb8c53f..71ecf52bf 100644
--- a/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst
+++ b/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst
@@ -5,4 +5,7 @@ When saving a passing test's output, this is the maximum size, in bytes, that
will be collected by the :command:`ctest_test` command. Defaults to 1024
(1 KiB).
+If a test's output contains the literal string "CTEST_FULL_OUTPUT",
+the output will not be truncated and may exceed the maximum size.
+
.. include:: CTEST_CUSTOM_XXX.txt
diff --git a/Help/variable/CTEST_SCRIPT_DIRECTORY.rst b/Help/variable/CTEST_SCRIPT_DIRECTORY.rst
new file mode 100644
index 000000000..77d4e58c9
--- /dev/null
+++ b/Help/variable/CTEST_SCRIPT_DIRECTORY.rst
@@ -0,0 +1,5 @@
+CTEST_SCRIPT_DIRECTORY
+----------------------
+
+The directory containing the top-level CTest script.
+The concept is similar to :variable:`CMAKE_SOURCE_DIR`.
diff --git a/Help/variable/EXECUTABLE_OUTPUT_PATH.rst b/Help/variable/EXECUTABLE_OUTPUT_PATH.rst
index 26d3e92a1..245b9eb26 100644
--- a/Help/variable/EXECUTABLE_OUTPUT_PATH.rst
+++ b/Help/variable/EXECUTABLE_OUTPUT_PATH.rst
@@ -3,6 +3,6 @@ EXECUTABLE_OUTPUT_PATH
Old executable location variable.
-The target property :prop_tgt:`RUNTIME_OUTPUT_DIRECTORY` supercedes this
+The target property :prop_tgt:`RUNTIME_OUTPUT_DIRECTORY` supersedes this
variable for a target if it is set. Executable targets are otherwise placed in
this directory.
diff --git a/Help/variable/MSVC_VERSION.rst b/Help/variable/MSVC_VERSION.rst
index 45df37fa0..241eb0384 100644
--- a/Help/variable/MSVC_VERSION.rst
+++ b/Help/variable/MSVC_VERSION.rst
@@ -20,5 +20,8 @@ Known version numbers are::
1910-1919 = VS 15.0 (v141 toolset)
1920-1929 = VS 16.0 (v142 toolset)
+..
+ 1930-1939 = VS 17.0 (v143 toolset)
+
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` and
:variable:`MSVC_TOOLSET_VERSION` variable.
diff --git a/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst b/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst
new file mode 100644
index 000000000..6718ecfd9
--- /dev/null
+++ b/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst
@@ -0,0 +1,21 @@
+<PROJECT-NAME>_IS_TOP_LEVEL
+---------------------------
+
+.. versionadded:: 3.21
+
+A boolean variable indicating whether the named project was called in a top
+level ``CMakeLists.txt`` file.
+
+To obtain the value from the most recent call to :command:`project` in
+the current directory scope or above, see the
+:variable:`PROJECT_IS_TOP_LEVEL` variable.
+
+The variable value will be true in:
+
+* the top-level directory of the project
+* the top-level directory of an external project added by :module:`ExternalProject`
+
+The variable value will be false in:
+
+* a directory added by :command:`add_subdirectory`
+* a directory added by :module:`FetchContent`
diff --git a/Help/variable/PROJECT_IS_TOP_LEVEL.rst b/Help/variable/PROJECT_IS_TOP_LEVEL.rst
new file mode 100644
index 000000000..ad61fecc0
--- /dev/null
+++ b/Help/variable/PROJECT_IS_TOP_LEVEL.rst
@@ -0,0 +1,31 @@
+PROJECT_IS_TOP_LEVEL
+--------------------
+
+.. versionadded:: 3.21
+
+A boolean variable indicating whether :command:`project` was called in a top
+level ``CMakeLists.txt`` file.
+
+Some modules should only be included as part of the top level
+``CMakeLists.txt`` file to not cause unintended side effects in the build
+tree, and this variable can be used to conditionally execute such code. For
+example, consider the :module:`CTest` module, which creates targets and
+options:
+
+.. code-block:: cmake
+
+ project(MyProject)
+ ...
+ if(PROJECT_IS_TOP_LEVEL)
+ include(CTest)
+ endif()
+
+The variable value will be true in:
+
+* the top-level directory of the project
+* the top-level directory of an external project added by :module:`ExternalProject`
+
+The variable value will be false in:
+
+* a directory added by :command:`add_subdirectory`
+* a directory added by :module:`FetchContent`
diff --git a/Modules/BasicConfigVersion-ExactVersion.cmake.in b/Modules/BasicConfigVersion-ExactVersion.cmake.in
index 3507a2283..c8d269500 100644
--- a/Modules/BasicConfigVersion-ExactVersion.cmake.in
+++ b/Modules/BasicConfigVersion-ExactVersion.cmake.in
@@ -18,14 +18,43 @@ endif()
set(PACKAGE_VERSION "@CVF_VERSION@")
-if("@CVF_VERSION@" MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)\\.") # strip the tweak version
- set(CVF_VERSION_NO_TWEAK "${CMAKE_MATCH_1}")
+if("@CVF_VERSION@" MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)") # strip the tweak version
+ set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(CVF_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(CVF_VERSION_PATCH "${CMAKE_MATCH_3}")
+
+ if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
+ endif()
+ if(NOT CVF_VERSION_MINOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" CVF_VERSION_MINOR "${CVF_VERSION_MINOR}")
+ endif()
+ if(NOT CVF_VERSION_PATCH VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" CVF_VERSION_PATCH "${CVF_VERSION_PATCH}")
+ endif()
+
+ set(CVF_VERSION_NO_TWEAK "${CVF_VERSION_MAJOR}.${CVF_VERSION_MINOR}.${CVF_VERSION_PATCH}")
else()
set(CVF_VERSION_NO_TWEAK "@CVF_VERSION@")
endif()
-if(PACKAGE_FIND_VERSION MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)\\.") # strip the tweak version
- set(REQUESTED_VERSION_NO_TWEAK "${CMAKE_MATCH_1}")
+if(PACKAGE_FIND_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)") # strip the tweak version
+ set(REQUESTED_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(REQUESTED_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(REQUESTED_VERSION_PATCH "${CMAKE_MATCH_3}")
+
+ if(NOT REQUESTED_VERSION_MAJOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" REQUESTED_VERSION_MAJOR "${REQUESTED_VERSION_MAJOR}")
+ endif()
+ if(NOT REQUESTED_VERSION_MINOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" REQUESTED_VERSION_MINOR "${REQUESTED_VERSION_MINOR}")
+ endif()
+ if(NOT REQUESTED_VERSION_PATCH VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" REQUESTED_VERSION_PATCH "${REQUESTED_VERSION_PATCH}")
+ endif()
+
+ set(REQUESTED_VERSION_NO_TWEAK
+ "${REQUESTED_VERSION_MAJOR}.${REQUESTED_VERSION_MINOR}.${REQUESTED_VERSION_PATCH}")
else()
set(REQUESTED_VERSION_NO_TWEAK "${PACKAGE_FIND_VERSION}")
endif()
diff --git a/Modules/BasicConfigVersion-SameMajorVersion.cmake.in b/Modules/BasicConfigVersion-SameMajorVersion.cmake.in
index dc04e54cd..cf73f603d 100644
--- a/Modules/BasicConfigVersion-SameMajorVersion.cmake.in
+++ b/Modules/BasicConfigVersion-SameMajorVersion.cmake.in
@@ -17,6 +17,9 @@ else()
if("@CVF_VERSION@" MATCHES "^([0-9]+)\\.")
set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
+ endif()
else()
set(CVF_VERSION_MAJOR "@CVF_VERSION@")
endif()
diff --git a/Modules/BasicConfigVersion-SameMinorVersion.cmake.in b/Modules/BasicConfigVersion-SameMinorVersion.cmake.in
index 9bb2efcfc..ef21df60f 100644
--- a/Modules/BasicConfigVersion-SameMinorVersion.cmake.in
+++ b/Modules/BasicConfigVersion-SameMinorVersion.cmake.in
@@ -19,6 +19,13 @@ else()
if("@CVF_VERSION@" MATCHES "^([0-9]+)\\.([0-9]+)")
set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(CVF_VERSION_MINOR "${CMAKE_MATCH_2}")
+
+ if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
+ endif()
+ if(NOT CVF_VERSION_MINOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" CVF_VERSION_MINOR "${CVF_VERSION_MINOR}")
+ endif()
else()
set(CVF_VERSION_MAJOR "@CVF_VERSION@")
set(CVF_VERSION_MINOR "")
@@ -44,6 +51,13 @@ else()
set(PACKAGE_VERSION_COMPATIBLE FALSE)
endif()
else()
+ if(NOT PACKAGE_FIND_VERSION_MAJOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" PACKAGE_FIND_VERSION_MAJOR "${PACKAGE_FIND_VERSION_MAJOR}")
+ endif()
+ if(NOT PACKAGE_FIND_VERSION_MINOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" PACKAGE_FIND_VERSION_MINOR "${PACKAGE_FIND_VERSION_MINOR}")
+ endif()
+
if((PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) AND
(PACKAGE_FIND_VERSION_MINOR STREQUAL CVF_VERSION_MINOR))
set(PACKAGE_VERSION_COMPATIBLE TRUE)
diff --git a/Modules/CMakeASM_NASMInformation.cmake b/Modules/CMakeASM_NASMInformation.cmake
index 97cb4880f..dad2750e8 100644
--- a/Modules/CMakeASM_NASMInformation.cmake
+++ b/Modules/CMakeASM_NASMInformation.cmake
@@ -38,6 +38,17 @@ if(NOT CMAKE_ASM_NASM_COMPILE_OBJECT)
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
endif()
+if(CMAKE_ASM_NASM_COMPILER_ID STREQUAL "NASM")
+ set(CMAKE_DEPFILE_FLAGS_ASM_NASM "-MD <DEP_FILE> -MT <DEP_TARGET>")
+
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake")
+ # dependencies are computed by the compiler itself
+ set(CMAKE_ASM_NASM_DEPFILE_FORMAT gcc)
+ set(CMAKE_ASM_NASM_DEPENDS_USE_COMPILER TRUE)
+ endif()
+endif()
+
# Load the generic ASMInformation file:
set(ASM_DIALECT "_NASM")
include(CMakeASMInformation)
diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in
index 7f73891fa..754f235ba 100644
--- a/Modules/CMakeCCompiler.cmake.in
+++ b/Modules/CMakeCCompiler.cmake.in
@@ -9,6 +9,8 @@ set(CMAKE_C_COMPILE_FEATURES "@CMAKE_C_COMPILE_FEATURES@")
set(CMAKE_C90_COMPILE_FEATURES "@CMAKE_C90_COMPILE_FEATURES@")
set(CMAKE_C99_COMPILE_FEATURES "@CMAKE_C99_COMPILE_FEATURES@")
set(CMAKE_C11_COMPILE_FEATURES "@CMAKE_C11_COMPILE_FEATURES@")
+set(CMAKE_C17_COMPILE_FEATURES "@CMAKE_C17_COMPILE_FEATURES@")
+set(CMAKE_C23_COMPILE_FEATURES "@CMAKE_C23_COMPILE_FEATURES@")
set(CMAKE_C_PLATFORM_ID "@CMAKE_C_PLATFORM_ID@")
set(CMAKE_C_SIMULATE_ID "@CMAKE_C_SIMULATE_ID@")
diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in
index 0bc8f5ade..1f19c00e2 100644
--- a/Modules/CMakeCCompilerId.c.in
+++ b/Modules/CMakeCCompilerId.c.in
@@ -11,6 +11,12 @@
# define volatile
#endif
+#if !defined(__has_include)
+/* If the compiler does not have __has_include, pretend the answer is
+ always no. */
+# define __has_include(x) 0
+#endif
+
@CMAKE_C_COMPILER_ID_CONTENT@
/* Construct the string literal in pieces to prevent the source from
@@ -39,6 +45,10 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
# else
# define C_DIALECT
# endif
+#elif __STDC_VERSION__ > 201710L
+# define C_DIALECT "23"
+#elif __STDC_VERSION__ >= 201710L
+# define C_DIALECT "17"
#elif __STDC_VERSION__ >= 201000L
# define C_DIALECT "11"
#elif __STDC_VERSION__ >= 199901L
diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake
index f6d620f40..6be186575 100644
--- a/Modules/CMakeCInformation.cmake
+++ b/Modules/CMakeCInformation.cmake
@@ -115,6 +115,11 @@ if(NOT CMAKE_C_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_C_COMPILER_LAUNCHER})
CACHE STRING "Compiler launcher for C.")
endif()
+if(NOT CMAKE_C_LINKER_LAUNCHER AND DEFINED ENV{CMAKE_C_LINKER_LAUNCHER})
+ set(CMAKE_C_LINKER_LAUNCHER "$ENV{CMAKE_C_LINKER_LAUNCHER}"
+ CACHE STRING "Linker launcher for C.")
+endif()
+
include(CMakeCommonLanguageInclude)
# now define the following rule variables
diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
index 5fd54c13a..a2946f458 100644
--- a/Modules/CMakeCUDAInformation.cmake
+++ b/Modules/CMakeCUDAInformation.cmake
@@ -9,15 +9,15 @@ endif()
set(CMAKE_INCLUDE_FLAG_CUDA "-I")
# Set implicit links early so compiler-specific modules can use them.
-set(__IMPLICT_LINKS )
+set(__IMPLICIT_LINKS)
foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
- string(APPEND __IMPLICT_LINKS " -L\"${dir}\"")
+ string(APPEND __IMPLICIT_LINKS " -L\"${dir}\"")
endforeach()
foreach(lib ${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES})
if(${lib} MATCHES "/")
- string(APPEND __IMPLICT_LINKS " \"${lib}\"")
+ string(APPEND __IMPLICIT_LINKS " \"${lib}\"")
else()
- string(APPEND __IMPLICT_LINKS " -l${lib}")
+ string(APPEND __IMPLICIT_LINKS " -l${lib}")
endif()
endforeach()
@@ -36,6 +36,25 @@ if(CMAKE_CUDA_COMPILER_ID)
endif()
+# This should be included before the _INIT variables are
+# used to initialize the cache. Since the rule variables
+# have if blocks on them, users can still define them here.
+# But, it should still be after the platform file so changes can
+# be made to those values.
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE)
+ # Save the full path of the file so try_compile can use it.
+ include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override)
+ set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}")
+endif()
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA)
+ # Save the full path of the file so try_compile can use it.
+ include(${CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA} RESULT_VARIABLE _override)
+ set(CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA "${_override}")
+endif()
+
+
if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_CUDA_FLAG)
set(CMAKE_SHARED_LIBRARY_RUNTIME_CUDA_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG})
endif()
@@ -110,17 +129,10 @@ include(CMakeCommonLanguageInclude)
# CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION
# CMAKE_CUDA_LINK_EXECUTABLE
-if(CMAKE_CUDA_HOST_COMPILER AND CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
- # FIXME: This is too late for the Platform/Windows-NVIDIA-CUDA module to
- # see it, so we do not support CMAKE_CUDA_HOST_COMPILER on Windows.
- # Move this to Compiler/NVIDIA-CUDA and update the VS generator too.
- string(APPEND _CMAKE_CUDA_EXTRA_FLAGS " -ccbin=<CMAKE_CUDA_HOST_COMPILER>")
-endif()
-
# create a shared library
if(NOT CMAKE_CUDA_CREATE_SHARED_LIBRARY)
set(CMAKE_CUDA_CREATE_SHARED_LIBRARY
- "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
+ "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
endif()
# create a shared module copy the shared library rule by default
@@ -160,32 +172,32 @@ endif()
# compile a cu file into an executable
if(NOT CMAKE_CUDA_LINK_EXECUTABLE)
set(CMAKE_CUDA_LINK_EXECUTABLE
- "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
+ "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
endif()
# Add implicit host link directories that contain device libraries
# to the device link line.
-set(__IMPLICT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
-if(__IMPLICT_DLINK_DIRS)
- list(REMOVE_ITEM __IMPLICT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
+set(__IMPLICIT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+if(__IMPLICIT_DLINK_DIRS)
+ list(REMOVE_ITEM __IMPLICIT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
endif()
-set(__IMPLICT_DLINK_FLAGS )
-foreach(dir ${__IMPLICT_DLINK_DIRS})
+set(__IMPLICIT_DLINK_FLAGS)
+foreach(dir ${__IMPLICIT_DLINK_DIRS})
if(EXISTS "${dir}/libcurand_static.a")
- string(APPEND __IMPLICT_DLINK_FLAGS " -L\"${dir}\"")
+ string(APPEND __IMPLICIT_DLINK_FLAGS " -L\"${dir}\"")
endif()
endforeach()
-unset(__IMPLICT_DLINK_DIRS)
+unset(__IMPLICIT_DLINK_DIRS)
#These are used when linking relocatable (dc) cuda code
if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY)
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICIT_DLINK_FLAGS}")
endif()
if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE)
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICIT_DLINK_FLAGS}")
endif()
# Used when device linking is handled by CMake.
@@ -193,6 +205,6 @@ if(NOT CMAKE_CUDA_DEVICE_LINK_COMPILE)
set(CMAKE_CUDA_DEVICE_LINK_COMPILE "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> -D__CUDA_INCLUDE_COMPILER_INTERNAL_HEADERS__ -D__NV_EXTRA_INITIALIZATION=\"\" -D__NV_EXTRA_FINALIZATION=\"\" -DREGISTERLINKBINARYFILE=\\\"<REGISTER_FILE>\\\" -DFATBINFILE=\\\"<FATBINARY>\\\" ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c \"${CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT}/bin/crt/link.stub\" -o <OBJECT>")
endif()
-unset(__IMPLICT_DLINK_FLAGS)
+unset(__IMPLICIT_DLINK_FLAGS)
set(CMAKE_CUDA_INFORMATION_LOADED 1)
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index 45acfe732..d0ce77a7e 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -44,7 +44,7 @@ if(CMAKE_COMPILER_IS_MINGW)
set(MINGW 1)
endif()
set(CMAKE_CXX_COMPILER_ID_RUN 1)
-set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP)
+set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm)
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
foreach (lang C OBJC OBJCXX)
diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in
index a67caba2c..7362a0837 100644
--- a/Modules/CMakeCXXCompilerId.cpp.in
+++ b/Modules/CMakeCXXCompilerId.cpp.in
@@ -5,6 +5,12 @@
# error "A C compiler has been selected for C++."
#endif
+#if !defined(__has_include)
+/* If the compiler does not have __has_include, pretend the answer is
+ always no. */
+# define __has_include(x) 0
+#endif
+
@CMAKE_CXX_COMPILER_ID_CONTENT@
/* Construct the string literal in pieces to prevent the source from
diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake
index dbb436675..944d23609 100644
--- a/Modules/CMakeCXXInformation.cmake
+++ b/Modules/CMakeCXXInformation.cmake
@@ -212,6 +212,11 @@ if(NOT CMAKE_CXX_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_CXX_COMPILER_LAUNCHER})
CACHE STRING "Compiler launcher for CXX.")
endif()
+if(NOT CMAKE_CXX_LINKER_LAUNCHER AND DEFINED ENV{CMAKE_CXX_LINKER_LAUNCHER})
+ set(CMAKE_CXX_LINKER_LAUNCHER "$ENV{CMAKE_CXX_LINKER_LAUNCHER}"
+ CACHE STRING "Linker launcher for CXX.")
+endif()
+
include(CMakeCommonLanguageInclude)
# now define the following rules:
diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
index 2dc75d694..05174de83 100644
--- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
+++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
@@ -8,7 +8,7 @@
macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR)
set(${_VAR}
- FAIL_REGEX "[Uu]nrecogni[sz]ed .*option" # GNU, NAG
+ FAIL_REGEX "[Uu]nrecogni[sz]ed .*option" # GNU, NAG, Fujitsu
FAIL_REGEX "switch .* is no longer supported" # GNU
FAIL_REGEX "unknown .*option" # Clang
FAIL_REGEX "optimization flag .* not supported" # Clang
diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake
index 214d58a8e..dd70d828f 100644
--- a/Modules/CMakeCompilerIdDetection.cmake
+++ b/Modules/CMakeCompilerIdDetection.cmake
@@ -13,12 +13,12 @@ endfunction()
function(compiler_id_detection outvar lang)
- if (NOT lang STREQUAL Fortran AND NOT lang STREQUAL CSharp
- AND NOT lang STREQUAL ISPC)
+ if (NOT "x${lang}" STREQUAL "xFortran" AND NOT "x${lang}" STREQUAL "xCSharp"
+ AND NOT "x${lang}" STREQUAL "xISPC")
file(GLOB lang_files
"${CMAKE_ROOT}/Modules/Compiler/*-DetermineCompiler.cmake")
set(nonlang CXX)
- if (lang STREQUAL CXX)
+ if ("x${lang}" STREQUAL "xCXX")
set(nonlang C)
endif()
@@ -42,7 +42,7 @@ function(compiler_id_detection outvar lang)
# Order is relevant here. For example, compilers which pretend to be
# GCC must appear before the actual GCC.
- if (lang STREQUAL CXX)
+ if ("x${lang}" STREQUAL "xCXX")
list(APPEND ordered_compilers
Comeau
)
@@ -66,10 +66,11 @@ function(compiler_id_detection outvar lang)
PGI
Cray
TI
+ FujitsuClang
Fujitsu
GHS
)
- if (lang STREQUAL C)
+ if ("x${lang}" STREQUAL "xC")
list(APPEND ordered_compilers
TinyCC
Bruce
@@ -80,19 +81,24 @@ function(compiler_id_detection outvar lang)
ARMCC
AppleClang
ARMClang
+ )
+ if(NOT __skip_rocmclang)
+ list(APPEND ordered_compilers ROCMClang)
+ endif()
+ list(APPEND ordered_compilers
Clang
GNU
MSVC
ADSP
IAR
)
- if (lang STREQUAL C)
+ if ("x${lang}" STREQUAL "xC")
list(APPEND ordered_compilers
SDCC
)
endif()
- if(lang STREQUAL CUDA)
+ if("x${lang}" STREQUAL "xCUDA")
set(ordered_compilers NVIDIA Clang)
endif()
diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake
index 96855d28f..0a291f24f 100644
--- a/Modules/CMakeDependentOption.cmake
+++ b/Modules/CMakeDependentOption.cmake
@@ -42,7 +42,10 @@ macro(CMAKE_DEPENDENT_OPTION option doc default depends force)
if(${option}_ISSET MATCHES "^${option}_ISSET$")
set(${option}_AVAILABLE 1)
foreach(d ${depends})
- string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}")
+ string(REPLACE "(" " ( " _CMAKE_CDO_DEP "${d}")
+ string(REPLACE ")" " ) " _CMAKE_CDO_DEP "${_CMAKE_CDO_DEP}")
+ string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${_CMAKE_CDO_DEP}")
+ unset(_CMAKE_CDO_DEP)
if(${CMAKE_DEPENDENT_OPTION_DEP})
else()
set(${option}_AVAILABLE 0)
diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake
index cd07ba983..0f80f9cff 100644
--- a/Modules/CMakeDetermineCCompiler.cmake
+++ b/Modules/CMakeDetermineCCompiler.cmake
@@ -85,6 +85,11 @@ else()
# ARMClang need target options
"--target=arm-arm-none-eabi -mcpu=cortex-m3"
+
+ # MSVC needs at least one include directory for __has_include to function,
+ # but custom toolchains may run MSVC with no INCLUDE env var and no -I flags.
+ # Also avoid linking so this works with no LIB env var.
+ "-c -I__does_not_exist__"
)
endif()
if(CMAKE_C_COMPILER_TARGET)
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index e7de9cc93..e360d3127 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -11,6 +11,9 @@ if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR
endif()
if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
+ if(DEFINED ENV{CUDAHOSTCXX} OR DEFINED CMAKE_CUDA_HOST_COMPILER)
+ message(WARNING "Visual Studio does not support specifying CUDAHOSTCXX or CMAKE_CUDA_HOST_COMPILER. Using the C++ compiler provided by Visual Studio.")
+ endif()
else()
if(NOT CMAKE_CUDA_COMPILER)
set(CMAKE_CUDA_COMPILER_INIT NOTFOUND)
@@ -31,19 +34,21 @@ else()
set(CMAKE_CUDA_COMPILER_LIST nvcc)
endif()
+ set(_CMAKE_CUDA_COMPILER_PATHS "$ENV{CUDA_PATH}/bin")
_cmake_find_compiler(CUDA)
+ unset(_CMAKE_CUDA_COMPILER_PATHS)
else()
_cmake_find_compiler_path(CUDA)
endif()
mark_as_advanced(CMAKE_CUDA_COMPILER)
-endif()
-#Allow the user to specify a host compiler
-if(NOT $ENV{CUDAHOSTCXX} STREQUAL "")
- get_filename_component(CMAKE_CUDA_HOST_COMPILER $ENV{CUDAHOSTCXX} PROGRAM)
- if(NOT EXISTS ${CMAKE_CUDA_HOST_COMPILER})
- message(FATAL_ERROR "Could not find compiler set in environment variable CUDAHOSTCXX:\n$ENV{CUDAHOSTCXX}.\n${CMAKE_CUDA_HOST_COMPILER}")
+ #Allow the user to specify a host compiler except for Visual Studio
+ if(NOT $ENV{CUDAHOSTCXX} STREQUAL "")
+ get_filename_component(CMAKE_CUDA_HOST_COMPILER $ENV{CUDAHOSTCXX} PROGRAM)
+ if(NOT EXISTS ${CMAKE_CUDA_HOST_COMPILER})
+ message(FATAL_ERROR "Could not find compiler set in environment variable CUDAHOSTCXX:\n$ENV{CUDAHOSTCXX}.\n${CMAKE_CUDA_HOST_COMPILER}")
+ endif()
endif()
endif()
diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake
index 3d1a7bba2..556518f49 100644
--- a/Modules/CMakeDetermineCXXCompiler.cmake
+++ b/Modules/CMakeDetermineCXXCompiler.cmake
@@ -80,6 +80,11 @@ else()
# ARMClang need target options
"--target=arm-arm-none-eabi -mcpu=cortex-m3"
+
+ # MSVC needs at least one include directory for __has_include to function,
+ # but custom toolchains may run MSVC with no INCLUDE env var and no -I flags.
+ # Also avoid linking so this works with no LIB env var.
+ "-c -I__does_not_exist__"
)
endif()
diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake
index c03a85fdb..a08e597f8 100644
--- a/Modules/CMakeDetermineCompileFeatures.cmake
+++ b/Modules/CMakeDetermineCompileFeatures.cmake
@@ -4,12 +4,14 @@
function(cmake_determine_compile_features lang)
- if(lang STREQUAL C AND COMMAND cmake_record_c_compile_features)
+ if("x${lang}" STREQUAL "xC" AND COMMAND cmake_record_c_compile_features)
message(CHECK_START "Detecting ${lang} compile features")
set(CMAKE_C90_COMPILE_FEATURES)
set(CMAKE_C99_COMPILE_FEATURES)
set(CMAKE_C11_COMPILE_FEATURES)
+ set(CMAKE_C17_COMPILE_FEATURES)
+ set(CMAKE_C23_COMPILE_FEATURES)
include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
@@ -20,6 +22,12 @@ function(cmake_determine_compile_features lang)
return()
endif()
+ if (CMAKE_C17_COMPILE_FEATURES AND CMAKE_C23_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_C23_COMPILE_FEATURES ${CMAKE_C17_COMPILE_FEATURES})
+ endif()
+ if (CMAKE_C11_COMPILE_FEATURES AND CMAKE_C17_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_C17_COMPILE_FEATURES ${CMAKE_C11_COMPILE_FEATURES})
+ endif()
if (CMAKE_C99_COMPILE_FEATURES AND CMAKE_C11_COMPILE_FEATURES)
list(REMOVE_ITEM CMAKE_C11_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES})
endif()
@@ -32,6 +40,8 @@ function(cmake_determine_compile_features lang)
${CMAKE_C90_COMPILE_FEATURES}
${CMAKE_C99_COMPILE_FEATURES}
${CMAKE_C11_COMPILE_FEATURES}
+ ${CMAKE_C17_COMPILE_FEATURES}
+ ${CMAKE_C23_COMPILE_FEATURES}
)
endif()
@@ -39,10 +49,12 @@ function(cmake_determine_compile_features lang)
set(CMAKE_C90_COMPILE_FEATURES ${CMAKE_C90_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_C99_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_C11_COMPILE_FEATURES ${CMAKE_C11_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_C17_COMPILE_FEATURES ${CMAKE_C17_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_C23_COMPILE_FEATURES ${CMAKE_C23_COMPILE_FEATURES} PARENT_SCOPE)
message(CHECK_PASS "done")
- elseif(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features)
+ elseif("x${lang}" STREQUAL "xCXX" AND COMMAND cmake_record_cxx_compile_features)
message(CHECK_START "Detecting ${lang} compile features")
set(CMAKE_CXX98_COMPILE_FEATURES)
@@ -98,7 +110,7 @@ function(cmake_determine_compile_features lang)
message(CHECK_PASS "done")
- elseif(lang STREQUAL CUDA AND COMMAND cmake_record_cuda_compile_features)
+ elseif("x${lang}" STREQUAL "xCUDA" AND COMMAND cmake_record_cuda_compile_features)
message(CHECK_START "Detecting ${lang} compile features")
set(CMAKE_CUDA03_COMPILE_FEATURES)
@@ -154,6 +166,62 @@ function(cmake_determine_compile_features lang)
message(CHECK_PASS "done")
+ elseif(lang STREQUAL HIP AND COMMAND cmake_record_hip_compile_features)
+ message(CHECK_START "Detecting ${lang} compile features")
+
+ set(CMAKE_HIP98_COMPILE_FEATURES)
+ set(CMAKE_HIP11_COMPILE_FEATURES)
+ set(CMAKE_HIP14_COMPILE_FEATURES)
+ set(CMAKE_HIP17_COMPILE_FEATURES)
+ set(CMAKE_HIP20_COMPILE_FEATURES)
+ set(CMAKE_HIP23_COMPILE_FEATURES)
+
+ include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
+
+ cmake_record_hip_compile_features()
+
+ if(NOT _result EQUAL 0)
+ message(CHECK_FAIL "failed")
+ return()
+ endif()
+
+ if (CMAKE_HIP20_COMPILE_FEATURES AND CMAKE_HIP23_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_HIP23_COMPILE_FEATURES ${CMAKE_HIP20_COMPILE_FEATURES})
+ endif()
+ if (CMAKE_HIP17_COMPILE_FEATURES AND CMAKE_HIP20_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_HIP20_COMPILE_FEATURES ${CMAKE_HIP17_COMPILE_FEATURES})
+ endif()
+ if (CMAKE_HIP14_COMPILE_FEATURES AND CMAKE_HIP17_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_HIP17_COMPILE_FEATURES ${CMAKE_HIP14_COMPILE_FEATURES})
+ endif()
+ if (CMAKE_HIP11_COMPILE_FEATURES AND CMAKE_HIP14_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_HIP14_COMPILE_FEATURES ${CMAKE_HIP11_COMPILE_FEATURES})
+ endif()
+ if (CMAKE_HIP98_COMPILE_FEATURES AND CMAKE_HIP11_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_HIP11_COMPILE_FEATURES ${CMAKE_HIP98_COMPILE_FEATURES})
+ endif()
+
+ if(NOT CMAKE_HIP_COMPILE_FEATURES)
+ set(CMAKE_HIP_COMPILE_FEATURES
+ ${CMAKE_HIP98_COMPILE_FEATURES}
+ ${CMAKE_HIP11_COMPILE_FEATURES}
+ ${CMAKE_HIP14_COMPILE_FEATURES}
+ ${CMAKE_HIP17_COMPILE_FEATURES}
+ ${CMAKE_HIP20_COMPILE_FEATURES}
+ ${CMAKE_HIP23_COMPILE_FEATURES}
+ )
+ endif()
+
+ set(CMAKE_HIP_COMPILE_FEATURES ${CMAKE_HIP_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_HIP98_COMPILE_FEATURES ${CMAKE_HIP98_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_HIP11_COMPILE_FEATURES ${CMAKE_HIP11_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_HIP14_COMPILE_FEATURES ${CMAKE_HIP14_COMPILE_FEATURES} PARENT_SCOPE)
+ 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)
+
+ message(CHECK_PASS "done")
+
endif()
endfunction()
diff --git a/Modules/CMakeDetermineCompiler.cmake b/Modules/CMakeDetermineCompiler.cmake
index 2780399dc..6430793ba 100644
--- a/Modules/CMakeDetermineCompiler.cmake
+++ b/Modules/CMakeDetermineCompiler.cmake
@@ -68,6 +68,16 @@ macro(_cmake_find_compiler lang)
)
endif()
find_program(CMAKE_${lang}_COMPILER NAMES ${CMAKE_${lang}_COMPILER_LIST} DOC "${lang} compiler")
+ if(_CMAKE_${lang}_COMPILER_PATHS)
+ # As a last fall-back, search in language-specific paths
+ find_program(CMAKE_${lang}_COMPILER
+ NAMES ${CMAKE_${lang}_COMPILER_LIST}
+ NAMES_PER_DIR
+ PATHS ${_CMAKE_${lang}_COMPILER_PATHS}
+ DOC "${lang} compiler"
+ NO_DEFAULT_PATH
+ )
+ endif()
if(CMAKE_${lang}_COMPILER_INIT AND NOT CMAKE_${lang}_COMPILER)
set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${CMAKE_${lang}_COMPILER_INIT}")
endif()
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index ad9503c58..bd1e73253 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -150,6 +150,40 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
endif()
endif()
+ # When invoked with HIPCC we need to extract the path to the underlying
+ # clang compiler when possible. This fixes the following issues:
+ # env variables can change how hipcc behaves
+ # allows us to properly find the binutils bundled with hip
+ if(CMAKE_${lang}_COMPILER_ID STREQUAL "ROCMClang"
+ AND CMAKE_${lang}_COMPILER MATCHES ".*hipcc")
+ get_filename_component(_hipcc_dir "${CMAKE_${lang}_COMPILER}" DIRECTORY)
+ execute_process(
+ COMMAND "${_hipcc_dir}/hipconfig"
+ --hipclangpath
+ OUTPUT_VARIABLE output
+ RESULT_VARIABLE result
+ )
+ if(result EQUAL 0 AND EXISTS "${output}")
+ if(lang STREQUAL "C")
+ set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${output}/clang")
+ set(CMAKE_${lang}_COMPILER "${output}/clang" PARENT_SCOPE)
+ else()
+ set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${output}/clang++")
+ set(CMAKE_${lang}_COMPILER "${output}/clang++" PARENT_SCOPE)
+ endif()
+ endif()
+ if(lang STREQUAL "HIP")
+ execute_process(
+ COMMAND "${_hipcc_dir}/hipconfig"
+ --rocmpath
+ OUTPUT_VARIABLE output
+ RESULT_VARIABLE result
+ )
+ if(result EQUAL 0)
+ set(_CMAKE_HIP_COMPILER_ROCM_ROOT "${output}" PARENT_SCOPE)
+ endif()
+ endif()
+ endif()
if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU")
execute_process(
@@ -166,6 +200,25 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
endif()
endif()
+ # The Fujitsu compiler does not always convey version information through
+ # preprocessor symbols so we extract through command line info
+ if (CMAKE_${lang}_COMPILER_ID STREQUAL "Fujitsu")
+ if(NOT CMAKE_${lang}_COMPILER_VERSION)
+ execute_process(
+ COMMAND "${CMAKE_${lang}_COMPILER}" -V
+ OUTPUT_VARIABLE output
+ ERROR_VARIABLE output
+ RESULT_VARIABLE result
+ TIMEOUT 10
+ )
+ if (result EQUAL 0)
+ if (output MATCHES [[Fujitsu [^ ]* Compiler ([0-9]+\.[0-9]+\.[0-9]+)]])
+ set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_MATCH_1}")
+ endif()
+ endif()
+ endif()
+ endif()
+
# if the format is unknown after all files have been checked, put "Unknown" in the cache
if(NOT CMAKE_EXECUTABLE_FORMAT)
set(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format")
@@ -204,6 +257,8 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
else()
set(CMAKE_${lang}_COMPILER_FRONTEND_VARIANT "GNU")
endif()
+ elseif("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xFujitsuClang")
+ set(CMAKE_${lang}_COMPILER_FRONTEND_VARIANT "GNU")
else()
set(CMAKE_${lang}_COMPILER_FRONTEND_VARIANT "")
endif()
@@ -299,7 +354,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
set(id_cl "$(CLToolExe)")
elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
set(id_cl clang.exe)
- # Executable names have choosen according documentation
+ # Executable names have been chosen according documentation
# URL: (https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-dpcpp-compiler/top.html#top_GUID-A9B4C91D-97AC-450D-9742-9D895BC8AEE1)
elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "Intel")
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "DPC\\+\\+ Compiler")
@@ -453,9 +508,19 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
set(id_ItemDefinitionGroup_entry "<CudaCompile>${cuda_target}<AdditionalOptions>%(AdditionalOptions)-v</AdditionalOptions><CodeGeneration>${cuda_codegen}</CodeGeneration></CudaCompile>")
set(id_PostBuildEvent_Command [[echo CMAKE_CUDA_COMPILER=$(CudaToolkitBinDir)\nvcc.exe]])
if(CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR)
- set(id_CudaToolkitCustomDir "<CudaToolkitCustomDir>${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}nvcc</CudaToolkitCustomDir>")
- string(CONCAT id_Import_props "<Import Project=\"${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}\\CUDAVisualStudioIntegration\\extras\\visual_studio_integration\\MSBuildExtensions\\${cuda_tools}.props\" />")
- string(CONCAT id_Import_targets "<Import Project=\"${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}\\CUDAVisualStudioIntegration\\extras\\visual_studio_integration\\MSBuildExtensions\\${cuda_tools}.targets\" />")
+ # check for legacy cuda custom toolkit folder structure
+ if(EXISTS ${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}nvcc)
+ set(id_CudaToolkitCustomDir "<CudaToolkitCustomDir>${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}nvcc</CudaToolkitCustomDir>")
+ else()
+ set(id_CudaToolkitCustomDir "<CudaToolkitCustomDir>${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}</CudaToolkitCustomDir>")
+ endif()
+ if(EXISTS ${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}CUDAVisualStudioIntegration)
+ string(CONCAT id_Import_props "<Import Project=\"${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}CUDAVisualStudioIntegration\\extras\\visual_studio_integration\\MSBuildExtensions\\${cuda_tools}.props\" />")
+ string(CONCAT id_Import_targets "<Import Project=\"${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}CUDAVisualStudioIntegration\\extras\\visual_studio_integration\\MSBuildExtensions\\${cuda_tools}.targets\" />")
+ else()
+ string(CONCAT id_Import_props "<Import Project=\"${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}\\extras\\visual_studio_integration\\MSBuildExtensions\\${cuda_tools}.props\" />")
+ string(CONCAT id_Import_targets "<Import Project=\"${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}\\extras\\visual_studio_integration\\MSBuildExtensions\\${cuda_tools}.targets\" />")
+ endif()
else()
string(CONCAT id_Import_props [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.props" />]])
string(CONCAT id_Import_targets [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.targets" />]])
@@ -821,8 +886,10 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION "${COMPILER_VERSION}")
endif()
if("${info}" MATCHES "INFO:compiler_version_internal\\[([^]\"]*)\\]")
- string(REGEX REPLACE "^0+([0-9])" "\\1" COMPILER_VERSION_INTERNAL "${CMAKE_MATCH_1}")
- string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION_INTERNAL "${COMPILER_VERSION_INTERNAL}")
+ set(COMPILER_VERSION_INTERNAL "${CMAKE_MATCH_1}")
+ string(REGEX REPLACE "^0+([0-9]+)" "\\1" COMPILER_VERSION_INTERNAL "${COMPILER_VERSION_INTERNAL}")
+ string(REGEX REPLACE "\\.0+([0-9]+)" ".\\1" COMPILER_VERSION_INTERNAL "${COMPILER_VERSION_INTERNAL}")
+ string(STRIP "${COMPILER_VERSION_INTERNAL}" COMPILER_VERSION_INTERNAL)
endif()
foreach(comp MAJOR MINOR PATCH TWEAK)
foreach(digit 1 2 3 4 5 6 7 8 9)
diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake
new file mode 100644
index 000000000..ed0110ae2
--- /dev/null
+++ b/Modules/CMakeDetermineHIPCompiler.cmake
@@ -0,0 +1,101 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
+include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
+
+if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR
+ ("${CMAKE_GENERATOR}" MATCHES "Ninja") ) )
+ message(FATAL_ERROR "HIP language not currently supported by \"${CMAKE_GENERATOR}\" generator")
+endif()
+
+
+if(NOT CMAKE_HIP_COMPILER)
+ set(CMAKE_HIP_COMPILER_INIT NOTFOUND)
+
+ # prefer the environment variable HIPCXX
+ if(NOT $ENV{HIPCXX} STREQUAL "")
+ get_filename_component(CMAKE_HIP_COMPILER_INIT $ENV{HIPCXX} PROGRAM PROGRAM_ARGS CMAKE_HIP_FLAGS_ENV_INIT)
+ if(CMAKE_HIP_FLAGS_ENV_INIT)
+ set(CMAKE_HIP_COMPILER_ARG1 "${CMAKE_HIP_FLAGS_ENV_INIT}" CACHE STRING "Arguments to CXX compiler")
+ endif()
+ if(NOT EXISTS ${CMAKE_HIP_COMPILER_INIT})
+ message(FATAL_ERROR "Could not find compiler set in environment variable HIPCXX:\n$ENV{HIPCXX}.\n${CMAKE_HIP_COMPILER_INIT}")
+ endif()
+ endif()
+
+ # finally list compilers to try
+ if(NOT CMAKE_HIP_COMPILER_INIT)
+ set(CMAKE_HIP_COMPILER_LIST hipcc clang++)
+ endif()
+
+ _cmake_find_compiler(HIP)
+else()
+ _cmake_find_compiler_path(HIP)
+endif()
+
+mark_as_advanced(CMAKE_HIP_COMPILER)
+
+# Build a small source file to identify the compiler.
+if(NOT CMAKE_HIP_COMPILER_ID_RUN)
+ set(CMAKE_HIP_COMPILER_ID_RUN 1)
+
+ # Try to identify the compiler.
+ set(CMAKE_HIP_COMPILER_ID)
+ set(CMAKE_HIP_PLATFORM_ID)
+ file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
+ CMAKE_HIP_COMPILER_ID_PLATFORM_CONTENT)
+
+ list(APPEND CMAKE_HIP_COMPILER_ID_TEST_FLAGS_FIRST "-v")
+
+ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
+ CMAKE_DETERMINE_COMPILER_ID(HIP HIPFLAGS CMakeHIPCompilerId.hip)
+
+ _cmake_find_compiler_sysroot(HIP)
+
+endif()
+
+if (NOT _CMAKE_TOOLCHAIN_LOCATION)
+ get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_HIP_COMPILER}" PATH)
+endif ()
+
+set(_CMAKE_PROCESSING_LANGUAGE "HIP")
+include(CMakeFindBinUtils)
+include(Compiler/${CMAKE_HIP_COMPILER_ID}-FindBinUtils OPTIONAL)
+unset(_CMAKE_PROCESSING_LANGUAGE)
+
+if(CMAKE_HIP_COMPILER_SYSROOT)
+ string(CONCAT _SET_CMAKE_HIP_COMPILER_SYSROOT
+ "set(CMAKE_HIP_COMPILER_SYSROOT \"${CMAKE_HIP_COMPILER_SYSROOT}\")\n"
+ "set(CMAKE_COMPILER_SYSROOT \"${CMAKE_HIP_COMPILER_SYSROOT}\")")
+else()
+ set(_SET_CMAKE_HIP_COMPILER_SYSROOT "")
+endif()
+
+if(CMAKE_HIP_COMPILER_ARCHITECTURE_ID)
+ set(_SET_CMAKE_HIP_COMPILER_ARCHITECTURE_ID
+ "set(CMAKE_HIP_COMPILER_ARCHITECTURE_ID ${CMAKE_HIP_COMPILER_ARCHITECTURE_ID})")
+else()
+ set(_SET_CMAKE_HIP_COMPILER_ARCHITECTURE_ID "")
+endif()
+
+if(MSVC_HIP_ARCHITECTURE_ID)
+ set(SET_MSVC_HIP_ARCHITECTURE_ID
+ "set(MSVC_HIP_ARCHITECTURE_ID ${MSVC_HIP_ARCHITECTURE_ID})")
+endif()
+
+if(NOT DEFINED CMAKE_HIP_ARCHITECTURES)
+ # Analyze output from hipcc to get the current GPU architecture.
+ if(CMAKE_HIP_COMPILER_PRODUCED_OUTPUT MATCHES " -target-cpu ([a-z0-9]+) ")
+ set(CMAKE_HIP_ARCHITECTURES "${CMAKE_MATCH_1}" CACHE STRING "HIP architectures")
+ else()
+ message(FATAL_ERROR "Failed to find a working HIP architecture.")
+ endif()
+endif()
+
+# configure variables set in this file for fast reload later on
+configure_file(${CMAKE_ROOT}/Modules/CMakeHIPCompiler.cmake.in
+ ${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPCompiler.cmake
+ @ONLY
+ )
+set(CMAKE_HIP_COMPILER_ENV_VAR "HIPCXX")
diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake
index bae270dec..8c7af067d 100644
--- a/Modules/CMakeDetermineSystem.cmake
+++ b/Modules/CMakeDetermineSystem.cmake
@@ -27,6 +27,7 @@
# Tru64 Tru64
# Ultrix ULTRIX
# cygwin CYGWIN_NT-5.1
+# MSYS MSYS_NT-6.1
# MacOSX Darwin
@@ -43,7 +44,7 @@ if(CMAKE_HOST_UNIX)
else()
exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
endif()
- if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|^GNU$|Android")
+ if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|MSYS.*|^GNU$|Android")
exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
RETURN_VALUE val)
elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
@@ -158,37 +159,14 @@ endif()
include(Platform/${CMAKE_SYSTEM_NAME}-Determine OPTIONAL)
-macro(ADJUST_CMAKE_SYSTEM_VARIABLES _PREFIX)
- if(NOT ${_PREFIX}_NAME)
- set(${_PREFIX}_NAME "UnknownOS")
- endif()
-
- # fix for BSD/OS , remove the /
- if(${_PREFIX}_NAME MATCHES BSD.OS)
- set(${_PREFIX}_NAME BSDOS)
- endif()
-
- # fix for GNU/kFreeBSD, remove the GNU/
- if(${_PREFIX}_NAME MATCHES kFreeBSD)
- set(${_PREFIX}_NAME kFreeBSD)
- endif()
-
- # fix for CYGWIN which has windows version in it
- if(${_PREFIX}_NAME MATCHES CYGWIN)
- set(${_PREFIX}_NAME CYGWIN)
- endif()
-
- # set CMAKE_SYSTEM to the CMAKE_SYSTEM_NAME
- set(${_PREFIX} ${${_PREFIX}_NAME})
- # if there is a CMAKE_SYSTEM_VERSION then add a -${CMAKE_SYSTEM_VERSION}
- if(${_PREFIX}_VERSION)
- set(${_PREFIX} ${${_PREFIX}}-${${_PREFIX}_VERSION})
- endif()
-
-endmacro()
-
-ADJUST_CMAKE_SYSTEM_VARIABLES(CMAKE_SYSTEM)
-ADJUST_CMAKE_SYSTEM_VARIABLES(CMAKE_HOST_SYSTEM)
+set(CMAKE_SYSTEM ${CMAKE_SYSTEM_NAME})
+if(CMAKE_SYSTEM_VERSION)
+ string(APPEND CMAKE_SYSTEM -${CMAKE_SYSTEM_VERSION})
+endif()
+set(CMAKE_HOST_SYSTEM ${CMAKE_HOST_SYSTEM_NAME})
+if(CMAKE_HOST_SYSTEM_VERSION)
+ string(APPEND CMAKE_HOST_SYSTEM -${CMAKE_HOST_SYSTEM_VERSION})
+endif()
# this file is also executed from cpack, then we don't need to generate these files
# in this case there is no CMAKE_BINARY_DIR
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index 4ce45af6d..3162ec57f 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -70,19 +70,30 @@ if(("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC" AND
OR (CMAKE_GENERATOR MATCHES "Visual Studio"
AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android"))
+ # Start with the canonical names.
set(_CMAKE_LINKER_NAMES "link")
set(_CMAKE_AR_NAMES "lib")
set(_CMAKE_MT_NAMES "mt")
+
+ # Prepend toolchain-specific names.
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xClang")
set(_CMAKE_NM_NAMES "llvm-nm" "nm")
- list(APPEND _CMAKE_AR_NAMES "lib" "llvm-lib")
- list(APPEND _CMAKE_MT_NAMES "mt" "llvm-mt")
- list(APPEND _CMAKE_LINKER_NAMES "lld-link")
+ list(PREPEND _CMAKE_AR_NAMES "llvm-lib")
+ list(PREPEND _CMAKE_MT_NAMES "llvm-mt")
+ list(PREPEND _CMAKE_LINKER_NAMES "lld-link")
list(APPEND _CMAKE_TOOL_VARS NM)
+ elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIntel")
+ list(PREPEND _CMAKE_AR_NAMES "xilib")
+ list(PREPEND _CMAKE_LINKER_NAMES "xilink")
endif()
list(APPEND _CMAKE_TOOL_VARS LINKER MT AR)
+elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^x(Open)?Watcom$")
+ set(_CMAKE_LINKER_NAMES "wlink")
+ set(_CMAKE_AR_NAMES "wlib")
+ list(APPEND _CMAKE_TOOL_VARS LINKER AR)
+
# in all other cases search for ar, ranlib, etc.
else()
if(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN)
@@ -92,50 +103,60 @@ else()
set(_CMAKE_TOOLCHAIN_LOCATION ${_CMAKE_TOOLCHAIN_LOCATION} ${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}/bin)
endif()
+ # Start with the canonical names.
+ set(_CMAKE_AR_NAMES "ar")
+ set(_CMAKE_RANLIB_NAMES "ranlib")
+ set(_CMAKE_STRIP_NAMES "strip")
+ set(_CMAKE_LINKER_NAMES "ld")
+ set(_CMAKE_NM_NAMES "nm")
+ set(_CMAKE_OBJDUMP_NAMES "objdump")
+ set(_CMAKE_OBJCOPY_NAMES "objcopy")
+ set(_CMAKE_READELF_NAMES "readelf")
+ set(_CMAKE_DLLTOOL_NAMES "dlltool")
+ set(_CMAKE_ADDR2LINE_NAMES "addr2line")
+
+ # Prepend toolchain-specific names.
if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang)
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC")
set(_CMAKE_LINKER_NAMES "lld-link")
else()
set(_CMAKE_LINKER_NAMES "ld.lld")
endif()
- list(APPEND _CMAKE_AR_NAMES "llvm-ar")
- list(APPEND _CMAKE_RANLIB_NAMES "llvm-ranlib")
- list(APPEND _CMAKE_STRIP_NAMES "llvm-strip")
- list(APPEND _CMAKE_NM_NAMES "llvm-nm")
- list(APPEND _CMAKE_OBJDUMP_NAMES "llvm-objdump")
- list(APPEND _CMAKE_OBJCOPY_NAMES "llvm-objcopy")
- list(APPEND _CMAKE_READELF_NAMES "llvm-readelf")
- list(APPEND _CMAKE_DLLTOOL_NAMES "llvm-dlltool")
- list(APPEND _CMAKE_ADDR2LINE_NAMES "llvm-addr2line")
+ list(PREPEND _CMAKE_AR_NAMES "llvm-ar")
+ list(PREPEND _CMAKE_RANLIB_NAMES "llvm-ranlib")
+ list(PREPEND _CMAKE_STRIP_NAMES "llvm-strip")
+ list(PREPEND _CMAKE_NM_NAMES "llvm-nm")
+ if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}" VERSION_GREATER_EQUAL 9)
+ # llvm-objdump versions prior to 9 did not support everything we need.
+ list(PREPEND _CMAKE_OBJDUMP_NAMES "llvm-objdump")
+ endif()
+ list(PREPEND _CMAKE_OBJCOPY_NAMES "llvm-objcopy")
+ list(PREPEND _CMAKE_READELF_NAMES "llvm-readelf")
+ list(PREPEND _CMAKE_DLLTOOL_NAMES "llvm-dlltool")
+ list(PREPEND _CMAKE_ADDR2LINE_NAMES "llvm-addr2line")
+ elseif("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL ARMClang)
+ list(PREPEND _CMAKE_AR_NAMES "armar")
+ list(PREPEND _CMAKE_LINKER_NAMES "armlink")
endif()
- list(APPEND _CMAKE_AR_NAMES "ar")
- list(APPEND _CMAKE_RANLIB_NAMES "ranlib")
- list(APPEND _CMAKE_STRIP_NAMES "strip")
- list(APPEND _CMAKE_LINKER_NAMES "ld")
- list(APPEND _CMAKE_NM_NAMES "nm")
- list(APPEND _CMAKE_OBJDUMP_NAMES "objdump")
- list(APPEND _CMAKE_OBJCOPY_NAMES "objcopy")
- list(APPEND _CMAKE_READELF_NAMES "readelf")
- list(APPEND _CMAKE_DLLTOOL_NAMES "dlltool")
- list(APPEND _CMAKE_ADDR2LINE_NAMES "addr2line")
-
- list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE)
+ list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE)
endif()
foreach(_CMAKE_TOOL IN LISTS _CMAKE_TOOL_VARS)
+ # Build the final list of prefixed/suffixed names.
+ set(_CMAKE_${_CMAKE_TOOL}_FIND_NAMES "")
foreach(_CMAKE_TOOL_NAME IN LISTS _CMAKE_${_CMAKE_TOOL}_NAMES)
- if(NOT _CMAKE_TOOLCHAIN_PREFIX STREQUAL "")
- if(NOT _CMAKE_TOOLCHAIN_SUFFIX STREQUAL "")
- list(PREPEND _CMAKE_${_CMAKE_TOOL}_NAMES ${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX})
- endif()
- list(PREPEND _CMAKE_${_CMAKE_TOOL}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME})
- endif()
- if(NOT _CMAKE_TOOLCHAIN_SUFFIX STREQUAL "")
- list(PREPEND _CMAKE_${_CMAKE_TOOL}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX})
- endif()
+ list(APPEND _CMAKE_${_CMAKE_TOOL}_FIND_NAMES
+ ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX}
+ ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME}
+ ${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX}
+ ${_CMAKE_TOOL_NAME}
+ )
endforeach()
- find_program(CMAKE_${_CMAKE_TOOL} NAMES ${_CMAKE_${_CMAKE_TOOL}_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+ list(REMOVE_DUPLICATES _CMAKE_${_CMAKE_TOOL}_FIND_NAMES)
+
+ find_program(CMAKE_${_CMAKE_TOOL} NAMES ${_CMAKE_${_CMAKE_TOOL}_FIND_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+ unset(_CMAKE_${_CMAKE_TOOL}_FIND_NAMES)
endforeach()
if(NOT CMAKE_RANLIB)
diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in
index 7aa385ed5..d0e0e46fb 100644
--- a/Modules/CMakeFortranCompilerId.F.in
+++ b/Modules/CMakeFortranCompilerId.F.in
@@ -26,7 +26,7 @@
PRINT *, 'INFO:compiler[IntelLLVM]'
! __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
! later. Look for 6 digit vs. 8 digit version number to decide encoding.
-! VVVV is no smaller than the current year when a versio is released.
+! VVVV is no smaller than the current year when a version is released.
# if __INTEL_LLVM_COMPILER < 1000000
# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
@@ -156,6 +156,15 @@
#define COMPILER_VERSION_MAJOR DEC(__NAG_COMPILER_RELEASE/10)
#define COMPILER_VERSION_MINOR DEC(__NAG_COMPILER_RELEASE % 10)
#define COMPILER_VERSION_PATCH DEC(__NAG_COMPILER_BUILD)
+#elif defined(__FUJITSU)
+ PRINT *, 'INFO:compiler[Fujitsu]'
+# if defined(__FRT_major__)
+# define COMPILER_VERSION_MAJOR DEC(__FRT_major__)
+# define COMPILER_VERSION_MINOR DEC(__FRT_minor__)
+# define COMPILER_VERSION_PATCH DEC(__FRT_patchlevel__)
+# elif defined(__FRT_version__)
+ PRINT *, 'INFO:compiler_version['//__FRT_version__//']'
+# endif
#else
PRINT *, 'INFO:compiler[]'
#endif
diff --git a/Modules/CMakeHIPCompiler.cmake.in b/Modules/CMakeHIPCompiler.cmake.in
new file mode 100644
index 000000000..9a30a45b3
--- /dev/null
+++ b/Modules/CMakeHIPCompiler.cmake.in
@@ -0,0 +1,58 @@
+set(CMAKE_HIP_COMPILER "@CMAKE_HIP_COMPILER@")
+set(CMAKE_HIP_COMPILER_ID "@CMAKE_HIP_COMPILER_ID@")
+set(CMAKE_HIP_COMPILER_VERSION "@CMAKE_HIP_COMPILER_VERSION@")
+set(CMAKE_HIP_STANDARD_COMPUTED_DEFAULT "@CMAKE_HIP_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_HIP_COMPILE_FEATURES "@CMAKE_HIP_COMPILE_FEATURES@")
+set(CMAKE_HIP98_COMPILE_FEATURES "@CMAKE_HIP03_COMPILE_FEATURES@")
+set(CMAKE_HIP11_COMPILE_FEATURES "@CMAKE_HIP11_COMPILE_FEATURES@")
+set(CMAKE_HIP14_COMPILE_FEATURES "@CMAKE_HIP14_COMPILE_FEATURES@")
+set(CMAKE_HIP17_COMPILE_FEATURES "@CMAKE_HIP17_COMPILE_FEATURES@")
+set(CMAKE_HIP20_COMPILE_FEATURES "@CMAKE_HIP20_COMPILE_FEATURES@")
+set(CMAKE_HIP23_COMPILE_FEATURES "@CMAKE_HIP23_COMPILE_FEATURES@")
+
+set(CMAKE_HIP_PLATFORM_ID "@CMAKE_HIP_PLATFORM_ID@")
+set(CMAKE_HIP_SIMULATE_ID "@CMAKE_HIP_SIMULATE_ID@")
+set(CMAKE_HIP_COMPILER_FRONTEND_VARIANT "@CMAKE_HIP_COMPILER_FRONTEND_VARIANT@")
+set(CMAKE_HIP_SIMULATE_VERSION "@CMAKE_HIP_SIMULATE_VERSION@")
+@SET_MSVC_HIP_ARCHITECTURE_ID@
+@_SET_CMAKE_HIP_COMPILER_SYSROOT@
+
+set(CMAKE_HIP_COMPILER_ENV_VAR "HIPCXX")
+
+set(CMAKE_HIP_COMPILER_LOADED 1)
+set(CMAKE_HIP_COMPILER_ID_RUN 1)
+set(CMAKE_HIP_SOURCE_FILE_EXTENSIONS hip)
+set(CMAKE_HIP_LINKER_PREFERENCE 90)
+set(CMAKE_HIP_LINKER_PREFERENCE_PROPAGATES 1)
+
+set(CMAKE_HIP_SIZEOF_DATA_PTR "@CMAKE_HIP_SIZEOF_DATA_PTR@")
+set(CMAKE_HIP_COMPILER_ABI "@CMAKE_HIP_COMPILER_ABI@")
+set(CMAKE_HIP_LIBRARY_ARCHITECTURE "@CMAKE_HIP_LIBRARY_ARCHITECTURE@")
+
+if(CMAKE_HIP_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_HIP_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_HIP_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_HIP_COMPILER_ABI}")
+endif()
+
+if(CMAKE_HIP_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_HIP_LIBRARY_ARCHITECTURE@")
+endif()
+
+set(CMAKE_HIP_TOOLKIT_INCLUDE_DIRECTORIES "@CMAKE_HIP_TOOLKIT_INCLUDE_DIRECTORIES@")
+
+set(CMAKE_HIP_IMPLICIT_INCLUDE_DIRECTORIES "@CMAKE_HIP_IMPLICIT_INCLUDE_DIRECTORIES@")
+set(CMAKE_HIP_IMPLICIT_LINK_LIBRARIES "@CMAKE_HIP_IMPLICIT_LINK_LIBRARIES@")
+set(CMAKE_HIP_IMPLICIT_LINK_DIRECTORIES "@CMAKE_HIP_IMPLICIT_LINK_DIRECTORIES@")
+set(CMAKE_HIP_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_HIP_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")
+
+set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED")
+
+set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_HIP_COMPILER_AR "@CMAKE_HIP_COMPILER_AR@")
+set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_HIP_COMPILER_RANLIB "@CMAKE_HIP_COMPILER_RANLIB@")
+set(CMAKE_LINKER "@CMAKE_LINKER@")
+set(CMAKE_MT "@CMAKE_MT@")
diff --git a/Modules/CMakeHIPCompilerABI.hip b/Modules/CMakeHIPCompilerABI.hip
new file mode 100644
index 000000000..6c912bd13
--- /dev/null
+++ b/Modules/CMakeHIPCompilerABI.hip
@@ -0,0 +1,16 @@
+#ifndef __HIP__
+# error "A C or C++ compiler has been selected for HIP"
+#endif
+
+#include "CMakeCompilerABI.h"
+
+int main(int argc, char* argv[])
+{
+ int require = 0;
+ require += info_sizeof_dptr[argc];
+#if defined(ABI_ID)
+ require += info_abi[argc];
+#endif
+ (void)argv;
+ return require;
+}
diff --git a/Modules/CMakeHIPCompilerId.hip.in b/Modules/CMakeHIPCompilerId.hip.in
new file mode 100644
index 000000000..5258efba0
--- /dev/null
+++ b/Modules/CMakeHIPCompilerId.hip.in
@@ -0,0 +1,54 @@
+#ifndef __HIP__
+# error "A C or C++ compiler has been selected for HIP"
+#endif
+
+@CMAKE_HIP_COMPILER_ID_CONTENT@
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+@CMAKE_HIP_COMPILER_ID_PLATFORM_CONTENT@
+@CMAKE_HIP_COMPILER_ID_ERROR_FOR_TEST@
+
+const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+#if __cplusplus > 202002L
+ "23"
+#elif __cplusplus > 201703L
+ "20"
+#elif __cplusplus >= 201703L
+ "17"
+#elif __cplusplus >= 201402L
+ "14"
+#elif __cplusplus >= 201103L
+ "11"
+#else
+ "98"
+#endif
+"]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+ require += info_language_dialect_default[argc];
+ (void)argv;
+ return require;
+}
diff --git a/Modules/CMakeHIPInformation.cmake b/Modules/CMakeHIPInformation.cmake
new file mode 100644
index 000000000..ec37e1c91
--- /dev/null
+++ b/Modules/CMakeHIPInformation.cmake
@@ -0,0 +1,139 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+if(UNIX)
+ set(CMAKE_HIP_OUTPUT_EXTENSION .o)
+else()
+ set(CMAKE_HIP_OUTPUT_EXTENSION .obj)
+endif()
+set(CMAKE_INCLUDE_FLAG_HIP "-I")
+
+# Load compiler-specific information.
+if(CMAKE_HIP_COMPILER_ID)
+ include(Compiler/${CMAKE_HIP_COMPILER_ID}-HIP OPTIONAL)
+endif()
+
+# load the system- and compiler specific files
+if(CMAKE_HIP_COMPILER_ID)
+ # load a hardware specific file, mostly useful for embedded compilers
+ if(CMAKE_SYSTEM_PROCESSOR)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_HIP_COMPILER_ID}-HIP-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+ endif()
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_HIP_COMPILER_ID}-HIP OPTIONAL)
+endif()
+
+
+if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG)
+ set(CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG_SEP)
+ set(CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_RPATH_LINK_HIP_FLAG)
+ set(CMAKE_SHARED_LIBRARY_RPATH_LINK_HIP_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG})
+endif()
+
+if(NOT DEFINED CMAKE_EXE_EXPORTS_HIP_FLAG)
+ set(CMAKE_EXE_EXPORTS_HIP_FLAG ${CMAKE_EXE_EXPORTS_C_FLAG})
+endif()
+
+if(NOT DEFINED CMAKE_SHARED_LIBRARY_SONAME_HIP_FLAG)
+ set(CMAKE_SHARED_LIBRARY_SONAME_HIP_FLAG ${CMAKE_SHARED_LIBRARY_SONAME_C_FLAG})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_HIP_FLAG)
+ set(CMAKE_EXECUTABLE_RUNTIME_HIP_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_HIP_FLAG_SEP)
+ set(CMAKE_EXECUTABLE_RUNTIME_HIP_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG_SEP})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RPATH_LINK_HIP_FLAG)
+ set(CMAKE_EXECUTABLE_RPATH_LINK_HIP_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_HIP_FLAG})
+endif()
+
+if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_HIP_WITH_RUNTIME_PATH)
+ set(CMAKE_SHARED_LIBRARY_LINK_HIP_WITH_RUNTIME_PATH ${CMAKE_SHARED_LIBRARY_LINK_C_WITH_RUNTIME_PATH})
+endif()
+
+
+# for most systems a module is the same as a shared library
+# so unless the variable CMAKE_MODULE_EXISTS is set just
+# copy the values from the LIBRARY variables
+if(NOT CMAKE_MODULE_EXISTS)
+ set(CMAKE_SHARED_MODULE_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_HIP_FLAGS})
+ set(CMAKE_SHARED_MODULE_CREATE_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_HIP_FLAGS})
+endif()
+
+# add the flags to the cache based
+# on the initial values computed in the platform/*.cmake files
+# use _INIT variables so that this only happens the first time
+# and you can set these flags in the cmake cache
+set(CMAKE_HIP_FLAGS_INIT "$ENV{HIPFLAGS} ${CMAKE_HIP_FLAGS_INIT}")
+
+cmake_initialize_per_config_variable(CMAKE_HIP_FLAGS "Flags used by the HIP compiler")
+
+if(CMAKE_HIP_STANDARD_LIBRARIES_INIT)
+ set(CMAKE_HIP_STANDARD_LIBRARIES "${CMAKE_HIP_STANDARD_LIBRARIES_INIT}"
+ CACHE STRING "Libraries linked by default with all HIP applications.")
+ mark_as_advanced(CMAKE_HIP_STANDARD_LIBRARIES)
+endif()
+
+if(NOT CMAKE_HIP_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_HIP_COMPILER_LAUNCHER})
+ set(CMAKE_HIP_COMPILER_LAUNCHER "$ENV{CMAKE_HIP_COMPILER_LAUNCHER}"
+ CACHE STRING "Compiler launcher for HIP.")
+endif()
+
+include(CMakeCommonLanguageInclude)
+
+# now define the following rules:
+# CMAKE_HIP_CREATE_SHARED_LIBRARY
+# CMAKE_HIP_CREATE_SHARED_MODULE
+# CMAKE_HIP_COMPILE_OBJECT
+# CMAKE_HIP_LINK_EXECUTABLE
+
+# create a shared library
+if(NOT CMAKE_HIP_CREATE_SHARED_LIBRARY)
+ set(CMAKE_HIP_CREATE_SHARED_LIBRARY
+ "<CMAKE_HIP_COMPILER> <CMAKE_SHARED_LIBRARY_HIP_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_HIP_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
+endif()
+
+# create a shared module copy the shared library rule by default
+if(NOT CMAKE_HIP_CREATE_SHARED_MODULE)
+ set(CMAKE_HIP_CREATE_SHARED_MODULE ${CMAKE_HIP_CREATE_SHARED_LIBRARY})
+endif()
+
+# Create a static archive incrementally for large object file counts.
+if(NOT DEFINED CMAKE_HIP_ARCHIVE_CREATE)
+ set(CMAKE_HIP_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_HIP_ARCHIVE_APPEND)
+ set(CMAKE_HIP_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_HIP_ARCHIVE_FINISH)
+ set(CMAKE_HIP_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
+endif()
+
+# compile a HIP file into an object file
+if(NOT CMAKE_HIP_COMPILE_OBJECT)
+ set(CMAKE_HIP_COMPILE_OBJECT
+ "<CMAKE_HIP_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> ${_CMAKE_COMPILE_AS_HIP_FLAG} -c <SOURCE>")
+endif()
+
+# compile a cu file into an executable
+if(NOT CMAKE_HIP_LINK_EXECUTABLE)
+ set(CMAKE_HIP_LINK_EXECUTABLE
+ "<CMAKE_HIP_COMPILER> <FLAGS> <CMAKE_HIP_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+endif()
+
+set(CMAKE_HIP_INFORMATION_LOADED 1)
+
+# Load the file and find the relevant HIP runtime.
+# This file will only exist after all compiler detection has finished
+include(${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPRuntime.cmake OPTIONAL)
+if(COMMAND _CMAKE_FIND_HIP_RUNTIME)
+ _CMAKE_FIND_HIP_RUNTIME()
+endif()
diff --git a/Modules/CMakeHIPRuntime.cmake.in b/Modules/CMakeHIPRuntime.cmake.in
new file mode 100644
index 000000000..ade26bb9b
--- /dev/null
+++ b/Modules/CMakeHIPRuntime.cmake.in
@@ -0,0 +1,99 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+function(_CMAKE_FIND_HIP_RUNTIME )
+ # Determined when hipcc is the HIP compiler
+ set(_CMAKE_HIP_COMPILER_ROCM_ROOT "@_CMAKE_HIP_COMPILER_ROCM_ROOT@")
+
+ # Forward facing value that can be provided by the user
+ set(CMAKE_HIP_COMPILER_TOOLKIT_ROOT @CMAKE_HIP_COMPILER_TOOLKIT_ROOT@)
+
+ if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET)
+ set(message_on_found TRUE)
+ endif()
+
+ set(explicit_search_only FALSE)
+ set(rocm_root_dirs )
+ if(DEFINED CMAKE_HIP_COMPILER_TOOLKIT_ROOT)
+ set(rocm_root_dirs "${CMAKE_HIP_COMPILER_TOOLKIT_ROOT}")
+ set(explicit_search_only TRUE)
+ set(error_message_location "the variable CMAKE_HIP_COMPILER_TOOLKIT_ROOT [\"${CMAKE_HIP_COMPILER_TOOLKIT_ROOT}\"]")
+ elseif(DEFINED ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT})
+ set(rocm_root_dirs "$ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT}")
+ set(explicit_search_only TRUE)
+ set(error_message_location "CMAKE_HIP_COMPILER_TOOLKIT_ROOT")
+ set(error_message_location "the environment variable CMAKE_HIP_COMPILER_TOOLKIT_ROOT [\"$ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT}\"]")
+ elseif(DEFINED _CMAKE_HIP_COMPILER_ROCM_ROOT)
+ set(rocm_root_dirs "${_CMAKE_HIP_COMPILER_ROCM_ROOT}")
+ set(explicit_search_only TRUE)
+ set(error_message_location "the associated hipconfig --rocmpath [\"${_CMAKE_HIP_COMPILER_ROCM_ROOT}\"]")
+ endif()
+
+ # Guess on where rocm is installed
+ if(NOT rocm_root_dirs AND (UNIX AND NOT APPLE))
+ set(platform_base "/opt/rocm-")
+
+ # Finad all default rocm installations
+ file(GLOB possible_paths "${platform_base}*")
+
+ set(versions)
+ foreach(p ${possible_paths})
+ # Extract version number from end of string
+ string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+$" p_version ${p})
+ if(IS_DIRECTORY ${p} AND p_version)
+ list(APPEND versions ${p_version})
+ endif()
+ endforeach()
+
+ # Sort numerically in descending order, so we try the newest versions first.
+ list(SORT versions COMPARE NATURAL ORDER DESCENDING)
+
+ # With a descending list of versions, populate possible paths to search.
+ set(rocm_root_dirs "/opt/rocm")
+ foreach(v IN LISTS versions)
+ list(APPEND rocm_root_dirs "${platform_base}${v}")
+ endforeach()
+ endif()
+
+ set(search_rel_path "/lib/cmake/hip-lang/")
+ list(TRANSFORM rocm_root_dirs APPEND "${search_rel_path}")
+
+ find_package(hip-lang
+ CONFIG
+ PATHS ${rocm_root_dirs}
+ QUIET
+ NO_DEFAULT_PATH
+ )
+ if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET AND NOT explicit_search_only)
+ find_package(hip-lang CONFIG QUIET)
+ endif()
+
+ if(DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET)
+ set(CMAKE_HIP_RUNTIME_LIBRARIES_STATIC
+ ${CMAKE_HIP_RUNTIME_LIBRARIES_STATIC}
+ ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET} PARENT_SCOPE)
+ set(CMAKE_HIP_RUNTIME_LIBRARIES_SHARED
+ ${CMAKE_HIP_RUNTIME_LIBRARIES_SHARED}
+ ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET} PARENT_SCOPE)
+ endif()
+
+ if(DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET AND message_on_found)
+ message(STATUS "Found HIP runtime: ${hip-lang_DIR}")
+ elseif(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET)
+ if(explicit_search_only)
+ set(error_message "Failed to find the HIP runtime, Could not find hip-lang-config.cmake at the following location(s):\n")
+ foreach(p IN LISTS rocm_root_dirs)
+ string(APPEND error_message "\t${p}\n")
+ endforeach()
+ string(APPEND "which are computed from the location specified by ${error_message_location}. \
+ Please specify CMAKE_HIP_COMPILER_TOOLKIT_ROOT to the location of")
+ message(FATAL_ERROR "${error_message}")
+ else()
+ message(FATAL_ERROR
+ "Failed to find the HIP runtime, Could not find hip-lang-config.cmake.\
+ Try setting CMAKE_HIP_COMPILER_TOOLKIT_ROOT")
+ endif()
+ endif()
+
+endfunction()
diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in
index 608adce0f..ab67bf396 100644
--- a/Modules/CMakeOBJCCompiler.cmake.in
+++ b/Modules/CMakeOBJCCompiler.cmake.in
@@ -9,6 +9,8 @@ set(CMAKE_OBJC_COMPILE_FEATURES "@CMAKE_OBJC_COMPILE_FEATURES@")
set(CMAKE_OBJC90_COMPILE_FEATURES "@CMAKE_OBJC90_COMPILE_FEATURES@")
set(CMAKE_OBJC99_COMPILE_FEATURES "@CMAKE_OBJC99_COMPILE_FEATURES@")
set(CMAKE_OBJC11_COMPILE_FEATURES "@CMAKE_OBJC11_COMPILE_FEATURES@")
+set(CMAKE_OBJC17_COMPILE_FEATURES "@CMAKE_OBJC17_COMPILE_FEATURES@")
+set(CMAKE_OBJC23_COMPILE_FEATURES "@CMAKE_OBJC23_COMPILE_FEATURES@")
set(CMAKE_OBJC_PLATFORM_ID "@CMAKE_OBJC_PLATFORM_ID@")
set(CMAKE_OBJC_SIMULATE_ID "@CMAKE_OBJC_SIMULATE_ID@")
diff --git a/Modules/CMakeOBJCCompilerId.m.in b/Modules/CMakeOBJCCompilerId.m.in
index 2b8aa3020..418fd4852 100644
--- a/Modules/CMakeOBJCCompilerId.m.in
+++ b/Modules/CMakeOBJCCompilerId.m.in
@@ -27,6 +27,10 @@ char const* qnxnto = "INFO" ":" "qnxnto[]";
# else
# define C_DIALECT
# endif
+#elif __STDC_VERSION__ > 201710L
+# define C_DIALECT "23"
+#elif __STDC_VERSION__ >= 201710L
+# define C_DIALECT "17"
#elif __STDC_VERSION__ >= 201000L
# define C_DIALECT "11"
#elif __STDC_VERSION__ >= 199901L
diff --git a/Modules/CMakeOBJCInformation.cmake b/Modules/CMakeOBJCInformation.cmake
index d53019175..ac67d013c 100644
--- a/Modules/CMakeOBJCInformation.cmake
+++ b/Modules/CMakeOBJCInformation.cmake
@@ -115,6 +115,11 @@ if(NOT CMAKE_OBJC_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_OBJC_COMPILER_LAUNCHER
CACHE STRING "Compiler launcher for OBJC.")
endif()
+if(NOT CMAKE_OBJC_LINKER_LAUNCHER AND DEFINED ENV{CMAKE_OBJC_LINKER_LAUNCHER})
+ set(CMAKE_OBJC_LINKER_LAUNCHER "$ENV{CMAKE_OBJC_LINKER_LAUNCHER}"
+ CACHE STRING "Linker launcher for OBJC.")
+endif()
+
include(CMakeCommonLanguageInclude)
# now define the following rule variables
diff --git a/Modules/CMakeOBJCXXInformation.cmake b/Modules/CMakeOBJCXXInformation.cmake
index 7a3b9d7d0..70e8579a9 100644
--- a/Modules/CMakeOBJCXXInformation.cmake
+++ b/Modules/CMakeOBJCXXInformation.cmake
@@ -208,6 +208,11 @@ if(NOT CMAKE_OBJCXX_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_OBJCXX_COMPILER_LAUN
CACHE STRING "Compiler launcher for OBJCXX.")
endif()
+if(NOT CMAKE_OBJCXX_LINKER_LAUNCHER AND DEFINED ENV{CMAKE_OBJCXX_LINKER_LAUNCHER})
+ set(CMAKE_OBJCXX_LINKER_LAUNCHER "$ENV{CMAKE_OBJCXX_LINKER_LAUNCHER}"
+ CACHE STRING "Linker launcher for OBJCXX.")
+endif()
+
include(CMakeCommonLanguageInclude)
# now define the following rules:
diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake
index ad719ef5a..5813956ee 100644
--- a/Modules/CMakePackageConfigHelpers.cmake
+++ b/Modules/CMakePackageConfigHelpers.cmake
@@ -143,12 +143,12 @@ The ``COMPATIBILITY`` mode ``AnyNewerVersion`` means that the installed
package version will be considered compatible if it is newer or exactly the
same as the requested version. This mode should be used for packages which
are fully backward compatible, also across major versions.
-If ``SameMajorVersion`` is used instead, then the behaviour differs from
+If ``SameMajorVersion`` is used instead, then the behavior differs from
``AnyNewerVersion`` in that the major version number must be the same as
requested, e.g. version 2.0 will not be considered compatible if 1.0 is
requested. This mode should be used for packages which guarantee backward
compatibility within the same major version.
-If ``SameMinorVersion`` is used, the behaviour is the same as
+If ``SameMinorVersion`` is used, the behavior is the same as
``SameMajorVersion``, but both major and minor version must be the same as
requested, e.g version 0.2 will not be compatible if 0.1 is requested.
If ``ExactVersion`` is used, then the package is only considered compatible if
diff --git a/Modules/CMakeParseImplicitIncludeInfo.cmake b/Modules/CMakeParseImplicitIncludeInfo.cmake
index 7cd75488c..5c0eda270 100644
--- a/Modules/CMakeParseImplicitIncludeInfo.cmake
+++ b/Modules/CMakeParseImplicitIncludeInfo.cmake
@@ -12,9 +12,9 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var)
set(log "")
# Cray compiler (from cray wrapper, via PrgEnv-cray)
- if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "Cray" AND
- "${line}" MATCHES "^/" AND "${line}" MATCHES "/ccfe |/ftnfe " AND
- "${line}" MATCHES " -isystem| -I")
+ if(CMAKE_${lang}_COMPILER_ID STREQUAL "Cray" AND
+ line MATCHES "^/" AND line MATCHES "/ccfe |/ftnfe " AND
+ line MATCHES " -isystem| -I")
string(REGEX MATCHALL " (-I ?|-isystem )(\"[^\"]+\"|[^ \"]+)" incs "${line}")
foreach(inc IN LISTS incs)
string(REGEX REPLACE " (-I ?|-isystem )(\"[^\"]+\"|[^ \"]+)" "\\2" idir "${inc}")
@@ -28,12 +28,12 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var)
endif()
# PGI compiler
- if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "PGI")
+ if(CMAKE_${lang}_COMPILER_ID STREQUAL "PGI")
# pgc++ verbose output differs
- if(("${lang}" STREQUAL "C" OR "${lang}" STREQUAL "Fortran") AND
- "${line}" MATCHES "^/" AND
- "${line}" MATCHES "/pgc |/pgf901 |/pgftnc " AND
- "${line}" MATCHES " -cmdline ")
+ if((lang STREQUAL "C" OR lang STREQUAL "Fortran") AND
+ line MATCHES "^/" AND
+ line MATCHES "/pgc |/pgf901 |/pgftnc " AND
+ line MATCHES " -cmdline ")
# cmdline has unparsed cmdline, remove it
string(REGEX REPLACE "-cmdline .*" "" line "${line}")
if("${line}" MATCHES " -nostdinc ")
@@ -51,14 +51,14 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var)
else()
string(APPEND log " warning: PGI C/F parse failed!\n")
endif()
- elseif("${lang}" STREQUAL "CXX" AND "${line}" MATCHES "^/" AND
- "${line}" MATCHES "/pggpp1 " AND "${line}" MATCHES " -I")
+ elseif(lang STREQUAL "CXX" AND line MATCHES "^/" AND
+ line MATCHES "/pggpp1 " AND line MATCHES " -I")
# oddly, -Mnostdinc does not get rid of system -I's, at least in
# PGI 18.10.1 ...
string(REGEX MATCHALL " (-I ?)([^ ]*)" incs "${line}")
foreach(inc IN LISTS incs)
string(REGEX REPLACE " (-I ?)([^ ]*)" "\\2" idir "${inc}")
- if(NOT "${idir}" STREQUAL "-") # filter out "-I-"
+ if(NOT idir STREQUAL "-") # filter out "-I-"
list(APPEND rv "${idir}")
endif()
endforeach()
@@ -71,8 +71,8 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var)
endif()
# SunPro compiler
- if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "SunPro" AND
- ("${line}" MATCHES "-D__SUNPRO_C" OR "${line}" MATCHES "-D__SUNPRO_F") )
+ if(CMAKE_${lang}_COMPILER_ID STREQUAL "SunPro" AND
+ (line MATCHES "-D__SUNPRO_C" OR line MATCHES "-D__SUNPRO_F"))
string(REGEX MATCHALL " (-I ?)([^ ]*)" incs "${line}")
foreach(inc IN LISTS incs)
string(REGEX REPLACE " (-I ?)([^ ]*)" "\\2" idir "${inc}")
@@ -81,7 +81,7 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var)
endif()
endforeach()
if(rv)
- if ("${lang}" STREQUAL "C" OR "${lang}" STREQUAL "CXX")
+ if (lang STREQUAL "C" OR lang STREQUAL "CXX")
# /usr/include appears to be hardwired in
list(APPEND rv "/usr/include")
endif()
@@ -92,24 +92,24 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var)
endif()
# XL compiler
- if(("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "XL"
- OR "${CMAKE_${lang}_COMPILER_ID}" STREQUAL "XLClang")
- AND "${line}" MATCHES "^/"
- AND ( ("${lang}" STREQUAL "Fortran" AND
- "${line}" MATCHES "/xl[fF]entry " AND
- "${line}" MATCHES "OSVAR\\([^ ]+\\)")
+ if((CMAKE_${lang}_COMPILER_ID STREQUAL "XL"
+ OR CMAKE_${lang}_COMPILER_ID STREQUAL "XLClang")
+ AND line MATCHES "^/"
+ AND ( (lang STREQUAL "Fortran" AND
+ line MATCHES "/xl[fF]entry " AND
+ line MATCHES "OSVAR\\([^ ]+\\)")
OR
- ( ("${lang}" STREQUAL "C" OR "${lang}" STREQUAL "CXX") AND
- "${line}" MATCHES "/xl[cC]2?entry " AND
- "${line}" MATCHES " -qosvar=")
+ ( (lang STREQUAL "C" OR lang STREQUAL "CXX") AND
+ line MATCHES "/xl[cC]2?entry " AND
+ line MATCHES " -qosvar=")
) )
# -qnostdinc cancels other stdinc flags, even if present
string(FIND "${line}" " -qnostdinc" nostd)
- if(NOT ${nostd} EQUAL -1)
+ if(NOT nostd EQUAL -1)
set(rv "") # defined but empty
string(APPEND log " got implicit includes via XL parser (nostdinc)\n")
else()
- if("${lang}" STREQUAL "CXX")
+ if(lang STREQUAL "CXX")
string(REGEX MATCHALL " -qcpp_stdinc=([^ ]*)" std "${line}")
string(REGEX MATCHALL " -qgcc_cpp_stdinc=([^ ]*)" gcc_std "${line}")
else()
@@ -146,6 +146,21 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var)
endif()
endif()
+ # Fujitsu compiler
+ if(CMAKE_${lang}_COMPILER_ID STREQUAL "Fujitsu" AND
+ line MATCHES "/ccpcom")
+ string(REGEX MATCHALL " (-I *|--sys_include=|--preinclude +)(\"[^\"]+\"|[^ \"]+)" incs "${line}")
+ foreach(inc IN LISTS incs)
+ string(REGEX REPLACE " (-I *|--sys_include=|--preinclude +)(\"[^\"]+\"|[^ \"]+)" "\\2" idir "${inc}")
+ list(APPEND rv "${idir}")
+ endforeach()
+ if(rv)
+ string(APPEND log " got implicit includes via fujitsu ccpcom parser!\n")
+ else()
+ string(APPEND log " warning: fujitsu ccpcom parse failed!\n")
+ endif()
+ endif()
+
if(log)
set(${log_var} "${log}" PARENT_SCOPE)
else()
diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake
index e848b5554..a61f71b11 100644
--- a/Modules/CMakeParseImplicitLinkInfo.cmake
+++ b/Modules/CMakeParseImplicitLinkInfo.cmake
@@ -72,6 +72,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
endif()
endif()
set(is_msvc 0)
+ set(search_static 0)
if("${cmd}" MATCHES "${linker_regex}")
string(APPEND log " link line: [${line}]\n")
string(REGEX REPLACE ";-([LYz]);" ";-\\1" args "${args}")
@@ -103,6 +104,10 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
elseif("${arg}" MATCHES "^-l([^:].*)$")
# Unix library.
set(lib "${CMAKE_MATCH_1}")
+ if(search_static AND lib MATCHES "^(gfortran|stdc\\+\\+)$")
+ # Search for the static library later, once all link dirs are known.
+ set(lib "SEARCH_STATIC:${lib}")
+ endif()
list(APPEND implicit_libs_tmp ${lib})
string(APPEND log " arg [${arg}] ==> lib [${lib}]\n")
elseif("${arg}" MATCHES "^(.:)?[/\\].*\\.a$")
@@ -129,6 +134,12 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
string(REPLACE ":" ";" dirs "${dirs}")
list(APPEND implicit_dirs_tmp ${dirs})
string(APPEND log " arg [${arg}] ==> dirs [${dirs}]\n")
+ elseif("${arg}" STREQUAL "-Bstatic")
+ set(search_static 1)
+ string(APPEND log " arg [${arg}] ==> search static\n" )
+ elseif("${arg}" STREQUAL "-Bdynamic")
+ set(search_static 0)
+ string(APPEND log " arg [${arg}] ==> search dynamic\n" )
elseif("${arg}" MATCHES "^-l:")
# HP named library.
list(APPEND implicit_libs_tmp ${arg})
@@ -172,8 +183,29 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
# We remove items that are not language-specific.
set(implicit_libs "")
foreach(lib IN LISTS implicit_libs_tmp)
+ if("x${lib}" MATCHES "^xSEARCH_STATIC:(.*)")
+ set(search_static 1)
+ set(lib "${CMAKE_MATCH_1}")
+ else()
+ set(search_static 0)
+ endif()
if("x${lib}" MATCHES "^x(crt.*\\.o|gcc_eh.*|.*libgcc_eh.*|System.*|.*libclang_rt.*|msvcrt.*|libvcruntime.*|libucrt.*|libcmt.*)$")
string(APPEND log " remove lib [${lib}]\n")
+ elseif(search_static)
+ # This library appears after a -Bstatic flag. Due to ordering
+ # and filtering for mixed-language link lines, we do not preserve
+ # the -Bstatic flag itself. Instead, use an absolute path.
+ # Search using a temporary variable with a distinct name
+ # so that our test suite does not depend on disk content.
+ find_library("CMAKE_${lang}_IMPLICIT_LINK_LIBRARY_${lib}" NO_CACHE NAMES "lib${lib}.a" NO_DEFAULT_PATH PATHS ${implicit_dirs_tmp})
+ set(_lib_static "${CMAKE_${lang}_IMPLICIT_LINK_LIBRARY_${lib}}")
+ if(_lib_static)
+ string(APPEND log " search lib [SEARCH_STATIC:${lib}] ==> [${_lib_static}]\n")
+ list(APPEND implicit_libs "${_lib_static}")
+ else()
+ string(APPEND log " search lib [SEARCH_STATIC:${lib}] ==> [${lib}]\n")
+ list(APPEND implicit_libs "${lib}")
+ endif()
elseif(IS_ABSOLUTE "${lib}")
get_filename_component(abs "${lib}" ABSOLUTE)
if(NOT "x${lib}" STREQUAL "x${abs}")
diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in
index 1dc12c060..59195f8e5 100644
--- a/Modules/CMakePlatformId.h.in
+++ b/Modules/CMakePlatformId.h.in
@@ -5,6 +5,9 @@
#if defined(__linux) || defined(__linux__) || defined(linux)
# define PLATFORM_ID "Linux"
+#elif defined(__MSYS__)
+# define PLATFORM_ID "MSYS"
+
#elif defined(__CYGWIN__)
# define PLATFORM_ID "Cygwin"
@@ -256,8 +259,12 @@
('0' + ((n)>>4 & 0xF)), \
('0' + ((n) & 0xF))
+/* Construct a string literal encoding the version number. */
+#ifdef COMPILER_VERSION
+char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]";
+
/* Construct a string literal encoding the version number components. */
-#ifdef COMPILER_VERSION_MAJOR
+#elif defined(COMPILER_VERSION_MAJOR)
char const info_version[] = {
'I', 'N', 'F', 'O', ':',
'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
@@ -281,6 +288,8 @@ char const info_version_internal[] = {
'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
'i','n','t','e','r','n','a','l','[',
COMPILER_VERSION_INTERNAL,']','\0'};
+#elif defined(COMPILER_VERSION_INTERNAL_STR)
+char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]";
#endif
/* Construct a string literal encoding the version number components. */
diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake
index d652ffa5c..8c25a737f 100644
--- a/Modules/CMakePrintHelpers.cmake
+++ b/Modules/CMakePrintHelpers.cmake
@@ -101,7 +101,10 @@ function(cmake_print_properties)
if(CPP_CACHE_ENTRIES)
set(items ${CPP_CACHE_ENTRIES})
set(mode ${mode} CACHE_ENTRIES)
- set(keyword CACHE)
+ # This is a workaround for the fact that passing `CACHE` as an argument to
+ # set() causes a cache variable to be set.
+ set(keyword "")
+ string(APPEND keyword CACHE)
endif()
if(NOT mode)
diff --git a/Modules/CMakeSystemSpecificInformation.cmake b/Modules/CMakeSystemSpecificInformation.cmake
index ea3a445b6..0ded56883 100644
--- a/Modules/CMakeSystemSpecificInformation.cmake
+++ b/Modules/CMakeSystemSpecificInformation.cmake
@@ -14,6 +14,7 @@
set(APPLE )
set(UNIX )
set(CYGWIN )
+set(MSYS )
set(WIN32 )
diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake
new file mode 100644
index 000000000..d9fcc9d8f
--- /dev/null
+++ b/Modules/CMakeTestHIPCompiler.cmake
@@ -0,0 +1,119 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+if(CMAKE_HIP_COMPILER_FORCED)
+ # The compiler configuration was forced by the user.
+ # Assume the user has configured all compiler information.
+ set(CMAKE_HIP_COMPILER_WORKS TRUE)
+ return()
+endif()
+
+set(__CMAKE_HIP_FLAGS "${CMAKE_HIP_FLAGS}")
+string(APPEND CMAKE_HIP_FLAGS "--cuda-host-only")
+
+include(CMakeTestCompilerCommon)
+
+# work around enforced code signing and / or missing executable target type
+set(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
+if(_CMAKE_FEATURE_DETECTION_TARGET_TYPE)
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_CMAKE_FEATURE_DETECTION_TARGET_TYPE})
+endif()
+
+# Remove any cached result from an older CMake version.
+# We now store this in CMakeHIPCompiler.cmake.
+unset(CMAKE_HIP_COMPILER_WORKS CACHE)
+
+# Try to identify the ABI and configure it into CMakeHIPCompiler.cmake
+include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
+CMAKE_DETERMINE_COMPILER_ABI(HIP ${CMAKE_ROOT}/Modules/CMakeHIPCompilerABI.hip)
+if(CMAKE_HIP_ABI_COMPILED)
+ # The compiler worked so skip dedicated test below.
+ set(CMAKE_HIP_COMPILER_WORKS TRUE)
+ message(STATUS "Check for working HIP compiler: ${CMAKE_HIP_COMPILER} - skipped")
+endif()
+
+# 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
+# is set and cmake stops processing commands and will not generate
+# any makefiles or projects.
+if(NOT CMAKE_HIP_COMPILER_WORKS)
+ PrintTestCompilerStatus("HIP")
+ __TestCompiler_setTryCompileTargetType()
+ file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testHIPCompiler.hip
+ "#ifndef __HIP__\n"
+ "# error \"The CMAKE_HIP_COMPILER is set to a C/CXX compiler\"\n"
+ "#endif\n"
+ "int main(){return 0;}\n")
+ try_compile(CMAKE_HIP_COMPILER_WORKS ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testHIPCompiler.hip
+ OUTPUT_VARIABLE __CMAKE_HIP_COMPILER_OUTPUT)
+ # Move result from cache to normal variable.
+ set(CMAKE_HIP_COMPILER_WORKS ${CMAKE_HIP_COMPILER_WORKS})
+ unset(CMAKE_HIP_COMPILER_WORKS CACHE)
+ __TestCompiler_restoreTryCompileTargetType()
+ if(NOT CMAKE_HIP_COMPILER_WORKS)
+ PrintTestCompilerResult(CHECK_FAIL "broken")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if the HIP compiler works failed with "
+ "the following output:\n${__CMAKE_HIP_COMPILER_OUTPUT}\n\n")
+ string(REPLACE "\n" "\n " _output "${__CMAKE_HIP_COMPILER_OUTPUT}")
+ message(FATAL_ERROR "The HIP compiler\n \"${CMAKE_HIP_COMPILER}\"\n"
+ "is not able to compile a simple test program.\nIt fails "
+ "with the following output:\n ${_output}\n\n"
+ "CMake will not be able to correctly generate this project.")
+ endif()
+ PrintTestCompilerResult(CHECK_PASS "works")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if the HIP compiler works passed with "
+ "the following output:\n${__CMAKE_HIP_COMPILER_OUTPUT}\n\n")
+endif()
+
+set(CMAKE_HIP_FLAGS "${__CMAKE_HIP_FLAGS}")
+unset(__CMAKE_HIP_FLAGS)
+
+
+# Try to identify the compiler features
+include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
+CMAKE_DETERMINE_COMPILE_FEATURES(HIP)
+
+
+# Setup the following:
+# Configure the new template file CMakeHipRuntime.cmake to
+# - ${CMAKE_PLATFORM_INFO_DIR}/
+# This file will do the actual find_package query. We than have
+# CMakeHIPInformation.cmake include `CMakeHipRuntime`
+# So it is included once system information has been finished
+#
+configure_file(
+ ${CMAKE_ROOT}/Modules/CMakeHIPRuntime.cmake.in
+ ${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPRuntime.cmake
+ @ONLY
+)
+
+# Re-configure to save learned information.
+configure_file(
+ ${CMAKE_ROOT}/Modules/CMakeHIPCompiler.cmake.in
+ ${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPCompiler.cmake
+ @ONLY
+ )
+include(${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPCompiler.cmake)
+
+if(CMAKE_HIP_SIZEOF_DATA_PTR)
+ foreach(f ${CMAKE_HIP_ABI_FILES})
+ include(${f})
+ endforeach()
+ unset(CMAKE_HIP_ABI_FILES)
+endif()
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE})
+unset(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE)
+unset(__CMAKE_HIP_COMPILER_OUTPUT)
+
+# Load the file and find the relevant HIP runtime.
+# This file will only exist after all compiler detection has finished
+include(${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPRuntime.cmake)
+if(COMMAND _CMAKE_FIND_HIP_RUNTIME)
+ _CMAKE_FIND_HIP_RUNTIME()
+endif()
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index ef5a7d5b1..373a70730 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -291,18 +291,27 @@ installers. The most commonly-used variables are:
Some compression methods used by CPack generators such as Debian or Archive
may take advantage of multiple CPU cores to speed up compression.
- ``CPACK_THREADS`` can be set to positive integer to specify how many threads
- will be used for compression. If it is set to 0, CPack will set it so that
- all available CPU cores are used.
+ ``CPACK_THREADS`` can be set to specify how many threads will be
+ used for compression.
+
+ A positive integer can be used to specify an exact desired thread count.
+
+ When given a negative integer CPack will use the absolute value
+ as the upper limit but may choose a lower value based on
+ the available hardware concurrency.
+
+ Given 0 CPack will try to use all available CPU cores.
+
By default ``CPACK_THREADS`` is set to ``1``.
- Currently only ``xz`` compression *may* take advantage of multiple cores. Other
- compression methods ignore this value and use only one thread.
+ Currently only ``xz`` compression *may* take advantage of multiple cores.
+ Other compression methods ignore this value and use only one thread.
- .. note::
+ .. versionadded:: 3.21
- Official CMake binaries available on ``cmake.org`` ship with a ``liblzma``
- that does not support parallel compression.
+ Official CMake binaries available on ``cmake.org`` now ship
+ with a ``liblzma`` that supports parallel compression.
+ Older versions did not.
Variables for Source Package Generators
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake
index d57cf18ba..2087a518b 100644
--- a/Modules/CPackIFW.cmake
+++ b/Modules/CPackIFW.cmake
@@ -125,6 +125,11 @@ The module defines the following commands:
list of dependency component or component group identifiers in
QtIFW style.
+ .. versionadded:: 3.21
+
+ Component or group names listed as dependencies may contain hyphens.
+ This requires QtIFW 3.1 or later.
+
``AUTO_DEPEND_ON``
.. versionadded:: 3.8
@@ -260,6 +265,11 @@ The module defines the following commands:
list of dependency component or component group identifiers in
QtIFW style.
+ .. versionadded:: 3.21
+
+ Component or group names listed as dependencies may contain hyphens.
+ This requires QtIFW 3.1 or later.
+
``AUTO_DEPEND_ON``
.. versionadded:: 3.8
diff --git a/Modules/CheckLinkerFlag.cmake b/Modules/CheckLinkerFlag.cmake
index 3c7a8286e..28ac2e32e 100644
--- a/Modules/CheckLinkerFlag.cmake
+++ b/Modules/CheckLinkerFlag.cmake
@@ -65,6 +65,8 @@ function(CHECK_LINKER_FLAG _lang _flag _var)
set (_source " program test\n stop\n end program")
elseif (_lang MATCHES "CUDA")
set (_source "__host__ int main() { return 0; }")
+ elseif (_lang MATCHES "HIP")
+ set (_source "__host__ int main() { return 0; }")
elseif (_lang MATCHES "^(OBJC|OBJCXX)$")
set (_source "#ifndef __OBJC__\n# error \"Not an Objective-C++ compiler\"\n#endif\nint main(void) { return 0; }")
else()
diff --git a/Modules/Compiler/ARMClang.cmake b/Modules/Compiler/ARMClang.cmake
index da7a43c90..c83922079 100644
--- a/Modules/Compiler/ARMClang.cmake
+++ b/Modules/Compiler/ARMClang.cmake
@@ -1,24 +1,22 @@
if(_ARMClang_CMAKE_LOADED)
return()
endif()
+
+# This file requires CMAKE_LINKER and CMAKE_AR set by CMakeFindBinUtils.cmake.
+if(NOT (DEFINED CMAKE_LINKER AND DEFINED CMAKE_AR))
+ return()
+endif()
+
set(_ARMClang_CMAKE_LOADED TRUE)
+# Save the CMP0123 setting in a variable used both below and by try_compile.
+cmake_policy(GET CMP0123 CMAKE_ARMClang_CMP0123)
+
cmake_policy(PUSH)
cmake_policy(SET CMP0057 NEW) # if IN_LIST
-get_filename_component(_CMAKE_C_TOOLCHAIN_LOCATION "${CMAKE_C_COMPILER}" PATH)
-get_filename_component(_CMAKE_CXX_TOOLCHAIN_LOCATION "${CMAKE_CXX_COMPILER}" PATH)
-
set(CMAKE_EXECUTABLE_SUFFIX ".elf")
-find_program(CMAKE_ARMClang_LINKER armlink HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" )
-find_program(CMAKE_ARMClang_AR armar HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" )
-
-set(CMAKE_LINKER "${CMAKE_ARMClang_LINKER}" CACHE FILEPATH "The ARMClang linker" FORCE)
-mark_as_advanced(CMAKE_ARMClang_LINKER)
-set(CMAKE_AR "${CMAKE_ARMClang_AR}" CACHE FILEPATH "The ARMClang archiver" FORCE)
-mark_as_advanced(CMAKE_ARMClang_AR)
-
if (CMAKE_LINKER MATCHES "armlink")
set(__CMAKE_ARMClang_USING_armlink TRUE)
set(CMAKE_LIBRARY_PATH_FLAG "--userlibpath=")
@@ -82,36 +80,53 @@ macro(__compiler_armclang lang)
if(NOT CMAKE_${lang}_COMPILER_ARCH_LIST)
__armclang_set_arch_list(${lang} CMAKE_${lang}_COMPILER_ARCH_LIST)
endif()
- if(NOT CMAKE_SYSTEM_PROCESSOR AND NOT CMAKE_SYSTEM_ARCH)
- message(FATAL_ERROR " CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n"
- " Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n"
- " Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}")
- else()
- __armclang_check_processor("${CMAKE_SYSTEM_ARCH}" "${CMAKE_${lang}_COMPILER_ARCH_LIST}" _CMAKE_${lang}_CHECK_ARCH_RESULT)
- if( _CMAKE_${lang}_CHECK_ARCH_RESULT)
- string(APPEND CMAKE_${lang}_FLAGS_INIT "-march=${CMAKE_SYSTEM_ARCH}")
- set(__march_flag_set TRUE)
+
+ # CMAKE_SYSTEM_PROCESSOR and CMAKE_SYSTEM_ARCH are not sufficient because they provide no
+ # information of additional CPU features needed in `-mcpu=<name>[+[no]<feature>+...]`.
+ # The automatic setting of compile and link options is deprecated and projects should specify their own.
+ cmake_policy(GET CMP0123 policy_CMP0123)
+ if(NOT "x${CMAKE_ARMClang_CMP0123}x" STREQUAL "xNEWx")
+ if(NOT "x${CMAKE_ARMClang_CMP0123}x" STREQUAL "xOLDx")
+ cmake_policy(GET_WARNING CMP0123 _cmp0123_warning)
+ message(AUTHOR_WARNING
+ "${_cmp0123_warning}\n"
+ "For compatibility, CMake will automatically add cpu/arch flags based "
+ "on the CMAKE_SYSTEM_PROCESSOR and/or CMAKE_SYSTEM_ARCH variables."
+ )
endif()
- __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}" _CMAKE_${lang}_CHECK_PROCESSOR_RESULT)
- if(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT)
- string(APPEND CMAKE_${lang}_FLAGS_INIT "-mcpu=${CMAKE_SYSTEM_PROCESSOR}")
- set(__mcpu_flag_set TRUE)
+
+ if(NOT CMAKE_SYSTEM_PROCESSOR AND NOT CMAKE_SYSTEM_ARCH)
+ message(FATAL_ERROR " CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n"
+ " Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n"
+ " Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}")
+ else()
+ __armclang_check_processor("${CMAKE_SYSTEM_ARCH}" "${CMAKE_${lang}_COMPILER_ARCH_LIST}" _CMAKE_${lang}_CHECK_ARCH_RESULT)
+ if( _CMAKE_${lang}_CHECK_ARCH_RESULT)
+ string(APPEND CMAKE_${lang}_FLAGS_INIT " -march=${CMAKE_SYSTEM_ARCH}")
+ set(__march_flag_set TRUE)
+ endif()
+ __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}" _CMAKE_${lang}_CHECK_PROCESSOR_RESULT)
+ if(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT)
+ string(APPEND CMAKE_${lang}_FLAGS_INIT " -mcpu=${CMAKE_SYSTEM_PROCESSOR}")
+ set(__mcpu_flag_set TRUE)
+ endif()
+ if(NOT __march_flag_set AND NOT __mcpu_flag_set)
+ message(FATAL_ERROR "At least one of the variables CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n"
+ "Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n"
+ " Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}")
+ endif()
+ unset(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT)
+ unset(_CMAKE_${lang}_CHECK_ARCH_RESULT)
endif()
- if(NOT __march_flag_set AND NOT __mcpu_flag_set)
- message(FATAL_ERROR "At least one of the variables CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n"
- "Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n"
- " Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}")
+
+ #check if CMAKE_SYSTEM_PROCESSOR belongs to supported cpu list for armlink
+ __armlink_set_cpu_list( ${lang} CMAKE_LINKER_CPU_LIST)
+ list(TRANSFORM CMAKE_LINKER_CPU_LIST TOLOWER)
+ __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_LINKER_CPU_LIST}" _CMAKE_CHECK_LINK_CPU_RESULT)
+ if(_CMAKE_CHECK_LINK_CPU_RESULT)
+ string(APPEND CMAKE_${lang}_LINK_FLAGS " --cpu=${CMAKE_SYSTEM_PROCESSOR}")
endif()
- unset(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT)
- unset(_CMAKE_${lang}_CHECK_ARCH_RESULT)
- endif()
- #check if CMAKE_SYSTEM_PROCESSOR belongs to supported cpu list for armlink
- __armlink_set_cpu_list( ${lang} CMAKE_LINKER_CPU_LIST)
- list(TRANSFORM CMAKE_LINKER_CPU_LIST TOLOWER)
- __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_LINKER_CPU_LIST}" _CMAKE_CHECK_LINK_CPU_RESULT)
- if(_CMAKE_CHECK_LINK_CPU_RESULT)
- string(APPEND CMAKE_${lang}_LINK_FLAGS "--cpu=${CMAKE_SYSTEM_PROCESSOR}")
endif()
if(__CMAKE_ARMClang_USING_armlink)
diff --git a/Modules/Compiler/AppleClang-C.cmake b/Modules/Compiler/AppleClang-C.cmake
index bd9819350..d711b6e65 100644
--- a/Modules/Compiler/AppleClang-C.cmake
+++ b/Modules/Compiler/AppleClang-C.cmake
@@ -28,4 +28,14 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0)
set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON)
endif()
-__compiler_check_default_language_standard(C 4.0 99)
+if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0)
+ set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17")
+ set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17")
+endif()
+
+if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0.3)
+ set(CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c2x")
+ set(CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu2x")
+endif()
+
+__compiler_check_default_language_standard(C 4.0 99 9.1 11 12.0.5 17)
diff --git a/Modules/Compiler/AppleClang-OBJC.cmake b/Modules/Compiler/AppleClang-OBJC.cmake
index d4eab4f63..f40c39615 100644
--- a/Modules/Compiler/AppleClang-OBJC.cmake
+++ b/Modules/Compiler/AppleClang-OBJC.cmake
@@ -23,4 +23,18 @@ if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.0)
set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON)
endif()
-__compiler_check_default_language_standard(OBJC 4.0 99)
+# AppleClang 10.0 was the oldest compiler available to test C17 support
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 10.0)
+ set(CMAKE_OBJC17_STANDARD_COMPILE_OPTION "-std=c17")
+ set(CMAKE_OBJC17_EXTENSION_COMPILE_OPTION "-std=gnu17")
+ set(CMAKE_OBJC17_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 11.0)
+ set(CMAKE_OBJC23_STANDARD_COMPILE_OPTION "-std=c2x")
+ set(CMAKE_OBJC23_EXTENSION_COMPILE_OPTION "-std=gnu2x")
+ set(CMAKE_OBJC23_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+# AppleClang 10.0 was the oldest compiler available to test default C11 support
+__compiler_check_default_language_standard(OBJC 4.0 99 10.0 11)
diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake
index cd897c527..c86af98f8 100644
--- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake
+++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake
@@ -64,6 +64,12 @@ endmacro()
# Define to allow compile features to be automatically determined
macro(cmake_record_c_compile_features)
set(_result 0)
+ if(_result EQUAL 0 AND DEFINED CMAKE_C23_STANDARD_COMPILE_OPTION)
+ _has_compiler_features_c(23)
+ endif()
+ if(_result EQUAL 0 AND DEFINED CMAKE_C17_STANDARD_COMPILE_OPTION)
+ _has_compiler_features_c(17)
+ endif()
if(_result EQUAL 0 AND DEFINED CMAKE_C11_STANDARD_COMPILE_OPTION)
if(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT)
_has_compiler_features_c(11)
@@ -164,3 +170,19 @@ macro(cmake_record_cuda_compile_features)
unset(CMAKE_CUDA03_STANDARD__HAS_FULL_SUPPORT)
endif()
endmacro()
+
+macro(cmake_record_hip_compile_features)
+ set(_result 0)
+ if(_result EQUAL 0 AND DEFINED CMAKE_HIP23_STANDARD_COMPILE_OPTION)
+ _has_compiler_features_hip(23)
+ endif()
+ if(_result EQUAL 0 AND DEFINED CMAKE_HIP20_STANDARD_COMPILE_OPTION)
+ _has_compiler_features_hip(20)
+ endif()
+ if(_result EQUAL 0 AND DEFINED CMAKE_HIP17_STANDARD_COMPILE_OPTION)
+ _has_compiler_features_hip(17)
+ endif()
+ _has_compiler_features_hip(14)
+ _has_compiler_features_hip(11)
+ _has_compiler_features_hip(98)
+endmacro()
diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake
index 5609abf47..cf493d720 100644
--- a/Modules/Compiler/Clang-C.cmake
+++ b/Modules/Compiler/Clang-C.cmake
@@ -25,37 +25,60 @@ elseif("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
endif()
endif()
-if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
- if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
+if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 2.1)
set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
- set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON)
set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99")
set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99")
- set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON)
+ endif()
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.1)
set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
- set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON)
- else()
- # clang-cl doesn't have any of these
- set(CMAKE_C90_STANDARD_COMPILE_OPTION "")
- set(CMAKE_C90_EXTENSION_COMPILE_OPTION "")
- set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON)
+ elseif(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.0)
+ set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c1x")
+ set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x")
+ endif()
+
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0)
+ set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17")
+ set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17")
+ endif()
+
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 9.0)
+ set(CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c2x")
+ set(CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu2x")
+ endif()
+else()
+ set(CMAKE_C90_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_C90_EXTENSION_COMPILE_OPTION "")
+ set(CMAKE_C99_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_C99_EXTENSION_COMPILE_OPTION "")
- set(CMAKE_C99_STANDARD_COMPILE_OPTION "")
- set(CMAKE_C99_EXTENSION_COMPILE_OPTION "")
- set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON)
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0)
+ set(CMAKE_C11_STANDARD_COMPILE_OPTION "/std:c11")
+ set(CMAKE_C11_EXTENSION_COMPILE_OPTION "/std:c11")
+ set(CMAKE_C17_STANDARD_COMPILE_OPTION "/std:c17")
+ set(CMAKE_C17_EXTENSION_COMPILE_OPTION "/std:c17")
+ else()
set(CMAKE_C11_STANDARD_COMPILE_OPTION "")
set(CMAKE_C11_EXTENSION_COMPILE_OPTION "")
- set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_C17_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_C17_EXTENSION_COMPILE_OPTION "")
endif()
endif()
-if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
- __compiler_check_default_language_standard(C 3.4 99 3.6 11)
-else()
- set(CMAKE_C_STANDARD_DEFAULT "")
+if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 2.1)
+ set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON)
+ set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON)
endif()
+
+if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.0)
+ set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+__compiler_check_default_language_standard(C 2.1 99 3.5.2 11 11.0 17)
diff --git a/Modules/Compiler/Clang-CUDA.cmake b/Modules/Compiler/Clang-CUDA.cmake
index cafc7ddd1..0223081da 100644
--- a/Modules/Compiler/Clang-CUDA.cmake
+++ b/Modules/Compiler/Clang-CUDA.cmake
@@ -22,8 +22,8 @@ set(_CMAKE_CUDA_PTX_FLAG "--cuda-device-only -S")
set(_CMAKE_CUDA_DEVICE_CODE "-fgpu-rdc -c")
# RulePlaceholderExpander expands crosscompile variables like sysroot and target only for CMAKE_<LANG>_COMPILER. Override the default.
-set(CMAKE_CUDA_LINK_EXECUTABLE "<CMAKE_CUDA_COMPILER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
-set(CMAKE_CUDA_CREATE_SHARED_LIBRARY "<CMAKE_CUDA_COMPILER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
+set(CMAKE_CUDA_LINK_EXECUTABLE "<CMAKE_CUDA_COMPILER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
+set(CMAKE_CUDA_CREATE_SHARED_LIBRARY "<CMAKE_CUDA_COMPILER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "STATIC")
set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "cudadevrt;cudart_static")
diff --git a/Modules/Compiler/Clang-HIP.cmake b/Modules/Compiler/Clang-HIP.cmake
new file mode 100644
index 000000000..1030a43cd
--- /dev/null
+++ b/Modules/Compiler/Clang-HIP.cmake
@@ -0,0 +1,20 @@
+include(Compiler/Clang)
+__compiler_clang(HIP)
+__compiler_clang_cxx_standards(HIP)
+
+set(_CMAKE_COMPILE_AS_HIP_FLAG "-x hip")
+set(_CMAKE_HIP_RDC_FLAG "-fgpu-rdc")
+
+if(NOT "x${CMAKE_HIP_SIMULATE_ID}" STREQUAL "xMSVC")
+ set(CMAKE_HIP_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
+
+ string(APPEND CMAKE_HIP_FLAGS_DEBUG_INIT " -O")
+endif()
+
+set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED")
+set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "")
+set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "")
+
+# Populated by CMakeHIPRuntime.cmake
+set(CMAKE_HIP_RUNTIME_LIBRARIES_STATIC "")
+set(CMAKE_HIP_RUNTIME_LIBRARIES_SHARED "")
diff --git a/Modules/Compiler/Clang-OBJC.cmake b/Modules/Compiler/Clang-OBJC.cmake
index 19179e36e..7a83b77fc 100644
--- a/Modules/Compiler/Clang-OBJC.cmake
+++ b/Modules/Compiler/Clang-OBJC.cmake
@@ -24,4 +24,16 @@ if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 3.4)
set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON)
endif()
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 6.0)
+ set(CMAKE_OBJC17_STANDARD_COMPILE_OPTION "-std=c17")
+ set(CMAKE_OBJC17_EXTENSION_COMPILE_OPTION "-std=gnu17")
+ set(CMAKE_OBJC17_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 9.0)
+ set(CMAKE_OBJC23_STANDARD_COMPILE_OPTION "-std=c2x")
+ set(CMAKE_OBJC23_EXTENSION_COMPILE_OPTION "-std=gnu2x")
+ set(CMAKE_OBJC23_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
__compiler_check_default_language_standard(OBJC 3.4 99 3.6 11)
diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake
index 7035d9346..f885eb023 100644
--- a/Modules/Compiler/Clang.cmake
+++ b/Modules/Compiler/Clang.cmake
@@ -56,6 +56,7 @@ else()
set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
string(COMPARE EQUAL "${CMAKE_${lang}_COMPILER_ID}" "AppleClang" __is_apple_clang)
+ string(COMPARE EQUAL "${CMAKE_${lang}_COMPILER_ID}" "FujitsuClang" __is_fujitsu_clang)
# '-flto=thin' available since Clang 3.9 and Xcode 8
# * http://clang.llvm.org/docs/ThinLTO.html#clang-llvm
@@ -65,6 +66,8 @@ else()
if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 8.0)
set(_CMAKE_LTO_THIN FALSE)
endif()
+ elseif(__is_fujitsu_clang)
+ set(_CMAKE_LTO_THIN FALSE)
else()
if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.9)
set(_CMAKE_LTO_THIN FALSE)
diff --git a/Modules/Compiler/Fujitsu-C.cmake b/Modules/Compiler/Fujitsu-C.cmake
new file mode 100644
index 000000000..dd31e4380
--- /dev/null
+++ b/Modules/Compiler/Fujitsu-C.cmake
@@ -0,0 +1,20 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+include(Compiler/Fujitsu)
+__compiler_fujitsu(C)
+
+if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 4)
+ set(CMAKE_C90_STANDARD_COMPILE_OPTION -std=c89)
+ set(CMAKE_C90_EXTENSION_COMPILE_OPTION -std=gnu89)
+ set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_C99_STANDARD_COMPILE_OPTION -std=c99)
+ set(CMAKE_C99_EXTENSION_COMPILE_OPTION -std=gnu99)
+ set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_C11_STANDARD_COMPILE_OPTION -std=c11)
+ set(CMAKE_C11_EXTENSION_COMPILE_OPTION -std=gnu11)
+ set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+__compiler_check_default_language_standard(C 4 11)
diff --git a/Modules/Compiler/Fujitsu-CXX.cmake b/Modules/Compiler/Fujitsu-CXX.cmake
new file mode 100644
index 000000000..0f42196e8
--- /dev/null
+++ b/Modules/Compiler/Fujitsu-CXX.cmake
@@ -0,0 +1,47 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+include(Compiler/Fujitsu)
+__compiler_fujitsu(CXX)
+
+#set(CMAKE_PCH_EXTENSION .pch)
+#set(CMAKE_PCH_EPILOGUE "#pragma hdrstop")
+#set(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH --no_pch_messages -include <PCH_HEADER> --use_pch <PCH_FILE>)
+#set(CMAKE_CXX_COMPILE_OPTIONS_CREATE_PCH --no_pch_messages -include <PCH_HEADER> --create_pch <PCH_FILE>)
+
+# The Fujitsu compiler offers both a 98 and 03 mode. These two are
+# essentially interchangeable as 03 simply provides clarity to some 98
+# ambiguyity.
+#
+# Re: Stroustrup's C++ FAQ:
+# What is the difference between C++98 and C++03?
+# From a programmer's view there is none. The C++03 revision of the
+# standard was a bug fix release for implementers to ensure greater
+# consistency and portability. In particular, tutorial and reference
+# material describing C++98 and C++03 can be used interchangeably by all
+# except compiler writers and standards gurus.
+#
+# Since CMake doesn't actually have an 03 mode and they're effectively
+# interchangeable then we're just going to explicitly use 03 mode in the
+# compiler when 98 is requested.
+
+# The version matching is messy here. The std support seems to be related to
+# the compiler tweak version derived from the patch id in the version string.
+
+if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 4)
+ set(CMAKE_CXX98_STANDARD_COMPILE_OPTION -std=c++03)
+ set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION -std=gnu++03)
+ set(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_CXX11_STANDARD_COMPILE_OPTION -std=c++11)
+ set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION -std=gnu++11)
+ set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_CXX14_STANDARD_COMPILE_OPTION -std=c++14)
+ set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION -std=gnu++14)
+ set(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_CXX17_STANDARD_COMPILE_OPTION -std=c++17)
+ set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION -std=gnu++17)
+endif()
+
+__compiler_check_default_language_standard(CXX 4 14)
diff --git a/Modules/Compiler/Fujitsu-DetermineCompiler.cmake b/Modules/Compiler/Fujitsu-DetermineCompiler.cmake
index 73ee38c87..853491610 100644
--- a/Modules/Compiler/Fujitsu-DetermineCompiler.cmake
+++ b/Modules/Compiler/Fujitsu-DetermineCompiler.cmake
@@ -1,2 +1,17 @@
-set(_compiler_id_pp_test "defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version)")
+set(_compiler_id_pp_test "defined(__FUJITSU)")
+
+set(_compiler_id_version_compute "
+# if defined(__FCC_version__)
+# define @PREFIX@COMPILER_VERSION __FCC_version__
+# elif defined(__FCC_major__)
+# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__FCC_major__)
+# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__FCC_minor__)
+# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__FCC_patchlevel__)
+# endif
+# if defined(__fcc_version)
+# define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__fcc_version)
+# elif defined(__FCC_VERSION)
+# define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__FCC_VERSION)
+# endif
+")
diff --git a/Modules/Compiler/Fujitsu-Fortran.cmake b/Modules/Compiler/Fujitsu-Fortran.cmake
new file mode 100644
index 000000000..face2d685
--- /dev/null
+++ b/Modules/Compiler/Fujitsu-Fortran.cmake
@@ -0,0 +1,16 @@
+include(Compiler/Fujitsu)
+__compiler_fujitsu(Fortran)
+
+set(CMAKE_Fortran_SUBMODULE_SEP ".")
+set(CMAKE_Fortran_SUBMODULE_EXT ".smod")
+
+set(CMAKE_Fortran_PREPROCESS_SOURCE
+ "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -Cpp -P <SOURCE> -o <PREPROCESSED_SOURCE>")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-Cpp")
+
+set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-Fixed")
+set(CMAKE_Fortran_FORMAT_FREE_FLAG "-Free")
+
+string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT "")
+
+set(CMAKE_Fortran_MODDIR_FLAG "-M ")
diff --git a/Modules/Compiler/Fujitsu.cmake b/Modules/Compiler/Fujitsu.cmake
new file mode 100644
index 000000000..78495cb93
--- /dev/null
+++ b/Modules/Compiler/Fujitsu.cmake
@@ -0,0 +1,43 @@
+# 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(__COMPILER_FUJITSU)
+ return()
+endif()
+set(__COMPILER_FUJITSU 1)
+
+include(Compiler/CMakeCommonCompilerMacros)
+
+macro(__compiler_fujitsu lang)
+ set(CMAKE_${lang}_VERBOSE_FLAG "-###")
+
+ # Initial configuration flags
+ string(APPEND CMAKE_${lang}_FLAGS_INIT " ")
+ string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g -O0")
+ string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3 -DNDEBUG")
+ string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG")
+
+ # PIC flags
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
+
+ # Passing link options to the compiler
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
+
+ # IPO flag
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+ if ("${lang}" STREQUAL "Fortran")
+ # Supported by Fortran compiler only
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-Klto")
+ else()
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+ endif()
+
+ # How to actually call the compiler
+ set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE
+ "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E $<$<COMPILE_LANGUAGE:Fortran>:-Cpp> <SOURCE> > <PREPROCESSED_SOURCE>")
+ set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
+endmacro()
diff --git a/Modules/Compiler/FujitsuClang-C.cmake b/Modules/Compiler/FujitsuClang-C.cmake
new file mode 100644
index 000000000..f700d2d52
--- /dev/null
+++ b/Modules/Compiler/FujitsuClang-C.cmake
@@ -0,0 +1,6 @@
+include(Compiler/FujitsuClang)
+
+set(_fjclang_ver "${CMAKE_C_COMPILER_VERSION_INTERNAL}")
+set(CMAKE_C_COMPILER_VERSION "${CMAKE_C_COMPILER_VERSION_INTERNAL}")
+include(Compiler/Clang-C)
+set(CMAKE_C_COMPILER_VERSION "${_fjclang_ver}")
diff --git a/Modules/Compiler/FujitsuClang-CXX.cmake b/Modules/Compiler/FujitsuClang-CXX.cmake
new file mode 100644
index 000000000..c8790cde3
--- /dev/null
+++ b/Modules/Compiler/FujitsuClang-CXX.cmake
@@ -0,0 +1,6 @@
+include(Compiler/FujitsuClang)
+
+set(_fjclang_ver "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}")
+set(CMAKE_CXX_COMPILER_VERSION "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}")
+include(Compiler/Clang-CXX)
+set(CMAKE_CXX_COMPILER_VERSION "${_fjclang_ver}")
diff --git a/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake b/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake
new file mode 100644
index 000000000..f6719b1b5
--- /dev/null
+++ b/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake
@@ -0,0 +1,9 @@
+
+set(_compiler_id_pp_test "defined(__CLANG_FUJITSU)")
+
+set(_compiler_id_version_compute "
+# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__FCC_major__)
+# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__FCC_minor__)
+# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__FCC_patchlevel__)
+# define @PREFIX@COMPILER_VERSION_INTERNAL_STR __clang_version__
+")
diff --git a/Modules/Compiler/FujitsuClang-FindBinUtils.cmake b/Modules/Compiler/FujitsuClang-FindBinUtils.cmake
new file mode 100644
index 000000000..4a6401d95
--- /dev/null
+++ b/Modules/Compiler/FujitsuClang-FindBinUtils.cmake
@@ -0,0 +1,6 @@
+if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "")
+ message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
+endif()
+
+set(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR ar)
+set(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB ranlib)
diff --git a/Modules/Compiler/FujitsuClang.cmake b/Modules/Compiler/FujitsuClang.cmake
new file mode 100644
index 000000000..a848248b2
--- /dev/null
+++ b/Modules/Compiler/FujitsuClang.cmake
@@ -0,0 +1,11 @@
+# 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(__COMPILER_FUJITSUCLANG)
+ return()
+endif()
+set(__COMPILER_FUJITSUCLANG 1)
+
+include(Compiler/Clang)
diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake
index 86b4d83e5..39e9c72c4 100644
--- a/Modules/Compiler/GNU-C.cmake
+++ b/Modules/Compiler/GNU-C.cmake
@@ -36,4 +36,14 @@ elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6)
set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x")
endif()
-__compiler_check_default_language_standard(C 3.4 90 5.0 11)
+if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1)
+ set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17")
+ set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17")
+endif()
+
+if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 9.1)
+ set(CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c23")
+ set(CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu23")
+endif()
+
+__compiler_check_default_language_standard(C 3.4 90 5.0 11 8.1 17)
diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake
index b8c077009..8bfc3efe4 100644
--- a/Modules/Compiler/IAR.cmake
+++ b/Modules/Compiler/IAR.cmake
@@ -66,10 +66,10 @@ macro(__compiler_iar_ilink lang)
string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG")
endif()
- set(CMAKE_${lang}_LINK_EXECUTABLE "\"${CMAKE_IAR_LINKER}\" --silent <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>")
- set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "\"${CMAKE_IAR_ARCHIVE}\" <TARGET> --create <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_CREATE "\"${CMAKE_IAR_ARCHIVE}\" <TARGET> --create <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_APPEND "\"${CMAKE_IAR_ARCHIVE}\" <TARGET> --replace <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> --silent <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>")
+ set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> <TARGET> --replace <LINK_FLAGS> <OBJECTS>")
set(CMAKE_${lang}_ARCHIVE_FINISH "")
set(CMAKE_LINKER "${CMAKE_IAR_LINKER}" CACHE FILEPATH "The IAR linker" FORCE)
@@ -102,9 +102,9 @@ macro(__compiler_iar_xlink lang)
string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG")
endif()
- set(CMAKE_${lang}_LINK_EXECUTABLE "\"${CMAKE_IAR_LINKER}\" -S <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>")
- set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "\"${CMAKE_IAR_AR}\" <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_CREATE "\"${CMAKE_IAR_AR}\" <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> -S <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>")
+ set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_${lang}_ARCHIVE_APPEND "")
set(CMAKE_${lang}_ARCHIVE_FINISH "")
diff --git a/Modules/Compiler/IntelLLVM-C.cmake b/Modules/Compiler/IntelLLVM-C.cmake
index 9b1c376b1..d69d06477 100644
--- a/Modules/Compiler/IntelLLVM-C.cmake
+++ b/Modules/Compiler/IntelLLVM-C.cmake
@@ -37,6 +37,9 @@ if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
+
+ set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17")
+ set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17")
else()
# clang-cl doesn't have any of these
set(CMAKE_C90_STANDARD_COMPILE_OPTION "")
@@ -47,8 +50,9 @@ else()
set(CMAKE_C11_STANDARD_COMPILE_OPTION "")
set(CMAKE_C11_EXTENSION_COMPILE_OPTION "")
+
+ set(CMAKE_C17_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_C17_EXTENSION_COMPILE_OPTION "")
endif()
-# FIXME: The compiler actually defaults to C17, but
-# CMake does not yet model or detect that standard.
-__compiler_check_default_language_standard(C 2020 11)
+__compiler_check_default_language_standard(C 2020 17)
diff --git a/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake b/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake
index 124dafe69..917a364ea 100644
--- a/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake
+++ b/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake
@@ -4,7 +4,7 @@ set(_compiler_id_pp_test "(defined(__clang__) && defined(__INTEL_CLANG_COMPILER)
set(_compiler_id_version_compute "
/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
* later. Look for 6 digit vs. 8 digit version number to decide encoding.
- * VVVV is no smaller than the current year when a versio is released.
+ * VVVV is no smaller than the current year when a version is released.
*/
#if __INTEL_LLVM_COMPILER < 1000000L
# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__INTEL_LLVM_COMPILER/100)
diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake
index a0f7c05e8..c2fe42df2 100644
--- a/Modules/Compiler/NVIDIA-CUDA.cmake
+++ b/Modules/Compiler/NVIDIA-CUDA.cmake
@@ -24,21 +24,17 @@ else()
set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
endif()
+if(CMAKE_CUDA_HOST_COMPILER AND NOT CMAKE_GENERATOR MATCHES "Visual Studio")
+ string(APPEND _CMAKE_CUDA_EXTRA_FLAGS " -ccbin=<CMAKE_CUDA_HOST_COMPILER>")
+endif()
+
if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89)
# The -MD flag was only added to nvcc in 10.2 so
# before that we had to invoke the compiler twice
# to get header dependency information
set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
else()
- if(CMAKE_CUDA_HOST_COMPILER AND NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
- # FIXME: Move the main -ccbin= flag from CMakeCUDAInformation to
- # a block above, remove this copy, and update the VS generator too.
- set(_CMAKE_CUDA_EXTRA_FLAGS_LOCAL " -ccbin=<CMAKE_CUDA_HOST_COMPILER>")
- else()
- set(_CMAKE_CUDA_EXTRA_FLAGS_LOCAL "")
- endif()
- set(CMAKE_CUDA_DEPENDS_EXTRA_COMMANDS "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS}${_CMAKE_CUDA_EXTRA_FLAGS_LOCAL} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -M <SOURCE> -MT <OBJECT> -o <DEP_FILE>")
- unset(_CMAKE_CUDA_EXTRA_FLAGS_LOCAL)
+ set(CMAKE_CUDA_DEPENDS_EXTRA_COMMANDS "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -M <SOURCE> -MT <OBJECT> -o <DEP_FILE>")
endif()
set(CMAKE_CUDA_DEPFILE_FORMAT gcc)
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
diff --git a/Modules/Compiler/OpenWatcom.cmake b/Modules/Compiler/OpenWatcom.cmake
index a9625137a..8cfe6838d 100644
--- a/Modules/Compiler/OpenWatcom.cmake
+++ b/Modules/Compiler/OpenWatcom.cmake
@@ -7,6 +7,7 @@ include_guard()
set(CMAKE_LIBRARY_PATH_FLAG "libpath ")
set(CMAKE_LINK_LIBRARY_FLAG "library ")
set(CMAKE_LINK_LIBRARY_FILE_FLAG "library ")
+set(CMAKE_LINK_OBJECT_FILE_FLAG "file ")
if(CMAKE_VERBOSE_MAKEFILE)
set(CMAKE_WCL_QUIET)
@@ -43,13 +44,13 @@ endforeach()
# C create import library
set(CMAKE_C_CREATE_IMPORT_LIBRARY
- "wlib -c -q -n -b <TARGET_IMPLIB> +<TARGET_QUOTED>")
+ "<CMAKE_AR> -c -q -n -b <TARGET_IMPLIB> +<TARGET_QUOTED>")
# C++ create import library
set(CMAKE_CXX_CREATE_IMPORT_LIBRARY ${CMAKE_C_CREATE_IMPORT_LIBRARY})
# C link a object files into an executable file
set(CMAKE_C_LINK_EXECUTABLE
- "wlink ${CMAKE_WLINK_QUIET} name <TARGET> <LINK_FLAGS> file {<OBJECTS>} <LINK_LIBRARIES>")
+ "<CMAKE_LINKER> ${CMAKE_WLINK_QUIET} name <TARGET> <LINK_FLAGS> file {<OBJECTS>} <LINK_LIBRARIES>")
# C++ link a object files into an executable file
set(CMAKE_CXX_LINK_EXECUTABLE ${CMAKE_C_LINK_EXECUTABLE})
@@ -69,19 +70,19 @@ set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE
# C create a shared library
set(CMAKE_C_CREATE_SHARED_LIBRARY
- "wlink ${CMAKE_WLINK_QUIET} name <TARGET> <LINK_FLAGS> option implib=<TARGET_IMPLIB> file {<OBJECTS>} <LINK_LIBRARIES>")
+ "<CMAKE_LINKER> ${CMAKE_WLINK_QUIET} name <TARGET> <LINK_FLAGS> option implib=<TARGET_IMPLIB> file {<OBJECTS>} <LINK_LIBRARIES>")
# C++ create a shared library
set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY})
# C create a shared module
set(CMAKE_C_CREATE_SHARED_MODULE
- "wlink ${CMAKE_WLINK_QUIET} name <TARGET> <LINK_FLAGS> file {<OBJECTS>} <LINK_LIBRARIES>")
+ "<CMAKE_LINKER> ${CMAKE_WLINK_QUIET} name <TARGET> <LINK_FLAGS> file {<OBJECTS>} <LINK_LIBRARIES>")
# C++ create a shared module
set(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_C_CREATE_SHARED_MODULE})
# C create a static library
set(CMAKE_C_CREATE_STATIC_LIBRARY
- "wlib ${CMAKE_LIB_QUIET} -c -n -b <TARGET_QUOTED> <LINK_FLAGS> <OBJECTS> ")
+ "<CMAKE_AR> ${CMAKE_LIB_QUIET} -c -n -b <TARGET_QUOTED> <LINK_FLAGS> <OBJECTS> ")
# C++ create a static library
set(CMAKE_CXX_CREATE_STATIC_LIBRARY ${CMAKE_C_CREATE_STATIC_LIBRARY})
diff --git a/Modules/Compiler/ROCMClang-ASM.cmake b/Modules/Compiler/ROCMClang-ASM.cmake
new file mode 100644
index 000000000..85d1110a5
--- /dev/null
+++ b/Modules/Compiler/ROCMClang-ASM.cmake
@@ -0,0 +1,2 @@
+include(Compiler/ROCMClang)
+__compiler_rocmclang(ASM)
diff --git a/Modules/Compiler/ROCMClang-C.cmake b/Modules/Compiler/ROCMClang-C.cmake
new file mode 100644
index 000000000..cdfa95d9e
--- /dev/null
+++ b/Modules/Compiler/ROCMClang-C.cmake
@@ -0,0 +1,7 @@
+include(Compiler/ROCMClang)
+__compiler_rocmclang(C)
+
+set(_rocm_clang_ver "${CMAKE_C_COMPILER_VERSION_INTERNAL}")
+set(CMAKE_C_COMPILER_VERSION "${CMAKE_C_COMPILER_VERSION_INTERNAL}")
+include(Compiler/Clang-C)
+set(CMAKE_C_COMPILER_VERSION "${_rocm_clang_ver}")
diff --git a/Modules/Compiler/ROCMClang-CXX.cmake b/Modules/Compiler/ROCMClang-CXX.cmake
new file mode 100644
index 000000000..5739c8e59
--- /dev/null
+++ b/Modules/Compiler/ROCMClang-CXX.cmake
@@ -0,0 +1,7 @@
+include(Compiler/ROCMClang)
+__compiler_rocmclang(CXX)
+
+set(_rocm_clang_ver "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}")
+set(CMAKE_CXX_COMPILER_VERSION "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}")
+include(Compiler/Clang-CXX)
+set(CMAKE_CXX_COMPILER_VERSION "${_rocm_clang_ver}")
diff --git a/Modules/Compiler/ROCMClang-DetermineCompiler.cmake b/Modules/Compiler/ROCMClang-DetermineCompiler.cmake
new file mode 100644
index 000000000..c2fc99b6b
--- /dev/null
+++ b/Modules/Compiler/ROCMClang-DetermineCompiler.cmake
@@ -0,0 +1,19 @@
+
+set(_compiler_id_pp_test "defined(__clang__) && __has_include(<hip/hip_version.h>)")
+
+set(_compiler_id_version_compute "
+# if defined(__clang__) && __has_include(<hip/hip_version.h>)
+# include <hip/hip_version.h>
+# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(HIP_VERSION_MAJOR)
+# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(HIP_VERSION_MINOR)
+# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(HIP_VERSION_PATCH)
+# endif")
+
+set(_compiler_id_simulate "
+# if defined(_MSC_VER)
+# define @PREFIX@SIMULATE_ID \"MSVC\"
+# elif defined(__clang__)
+# define @PREFIX@SIMULATE_ID \"Clang\"
+# elif defined(__GNUC__)
+# define @PREFIX@SIMULATE_ID \"GNU\"
+# endif")
diff --git a/Modules/Compiler/ROCMClang-FindBinUtils.cmake b/Modules/Compiler/ROCMClang-FindBinUtils.cmake
new file mode 100644
index 000000000..e721c8708
--- /dev/null
+++ b/Modules/Compiler/ROCMClang-FindBinUtils.cmake
@@ -0,0 +1 @@
+include(Compiler/Clang-FindBinUtils)
diff --git a/Modules/Compiler/ROCMClang-HIP.cmake b/Modules/Compiler/ROCMClang-HIP.cmake
new file mode 100644
index 000000000..7af769987
--- /dev/null
+++ b/Modules/Compiler/ROCMClang-HIP.cmake
@@ -0,0 +1,49 @@
+include(Compiler/ROCMClang)
+__compiler_rocmclang(HIP)
+
+set(_CMAKE_COMPILE_AS_HIP_FLAG "-x hip")
+set(_CMAKE_HIP_RDC_FLAG "-fgpu-rdc")
+
+if(NOT "x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC")
+ set(CMAKE_HIP_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
+ string(APPEND CMAKE_HIP_FLAGS_DEBUG_INIT " -O")
+endif()
+
+if(CMAKE_HIP_SIMULATE_ID STREQUAL "GNU")
+ set(CMAKE_HIP_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_HIP_LINKER_WRAPPER_FLAG_SEP ",")
+elseif(CMAKE_HIP_SIMULATE_ID STREQUAL "Clang")
+ set(CMAKE_HIP_LINKER_WRAPPER_FLAG "-Xlinker" " ")
+ set(CMAKE_HIP_LINKER_WRAPPER_FLAG_SEP)
+endif()
+
+if(NOT CMAKE_HIP_COMPILER_VERSION VERSION_LESS 1.0)
+ set(CMAKE_HIP98_STANDARD_COMPILE_OPTION "-std=c++98")
+ set(CMAKE_HIP98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
+ set(CMAKE_HIP98_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_HIP11_STANDARD_COMPILE_OPTION "-std=c++11")
+ set(CMAKE_HIP11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
+ set(CMAKE_HIP11_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_HIP14_STANDARD_COMPILE_OPTION "-std=c++14")
+ set(CMAKE_HIP14_EXTENSION_COMPILE_OPTION "-std=gnu++14")
+ set(CMAKE_HIP14_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_HIP17_STANDARD_COMPILE_OPTION "-std=c++17")
+ set(CMAKE_HIP17_EXTENSION_COMPILE_OPTION "-std=gnu++17")
+ set(CMAKE_HIP17_STANDARD__HAS_FULL_SUPPORT ON)
+
+ set(CMAKE_HIP20_STANDARD_COMPILE_OPTION "-std=c++20")
+ set(CMAKE_HIP20_EXTENSION_COMPILE_OPTION "-std=gnu++20")
+endif()
+
+set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED")
+set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "")
+set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "")
+
+# Populated by CMakeHIPRuntime.cmake
+set(CMAKE_HIP_RUNTIME_LIBRARIES_STATIC "")
+set(CMAKE_HIP_RUNTIME_LIBRARIES_SHARED "")
+
+__compiler_check_default_language_standard(HIP 3.5 11)
diff --git a/Modules/Compiler/ROCMClang-OBJC.cmake b/Modules/Compiler/ROCMClang-OBJC.cmake
new file mode 100644
index 000000000..794973d33
--- /dev/null
+++ b/Modules/Compiler/ROCMClang-OBJC.cmake
@@ -0,0 +1,7 @@
+include(Compiler/ROCMClang)
+__compiler_rocmclang(OBJC)
+
+set(_rocm_clang_ver "${CMAKE_OBJC_COMPILER_VERSION_INTERNAL}")
+set(CMAKE_OBJC_COMPILER_VERSION "${CMAKE_OBJC_COMPILER_VERSION_INTERNAL}")
+include(Compiler/Clang-OBJC)
+set(CMAKE_OBJC_COMPILER_VERSION "${_rocm_clang_ver}")
diff --git a/Modules/Compiler/ROCMClang-OBJCXX.cmake b/Modules/Compiler/ROCMClang-OBJCXX.cmake
new file mode 100644
index 000000000..82238e167
--- /dev/null
+++ b/Modules/Compiler/ROCMClang-OBJCXX.cmake
@@ -0,0 +1,7 @@
+include(Compiler/ROCMClang)
+__compiler_rocmclang(OBJCXX)
+
+set(_rocm_clang_ver "${CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL}")
+set(CMAKE_OBJCXX_COMPILER_VERSION "${CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL}")
+include(Compiler/Clang-OBJCXX)
+set(CMAKE_OBJCXX_COMPILER_VERSION "${_rocm_clang_ver}")
diff --git a/Modules/Compiler/ROCMClang.cmake b/Modules/Compiler/ROCMClang.cmake
new file mode 100644
index 000000000..6b38c2d40
--- /dev/null
+++ b/Modules/Compiler/ROCMClang.cmake
@@ -0,0 +1,35 @@
+# 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.
+include_guard()
+
+include(Compiler/CMakeCommonCompilerMacros)
+
+macro(__compiler_rocmclang lang)
+
+ set(CMAKE_${lang}_VERBOSE_FLAG "-v")
+
+ if(NOT "x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC")
+ # Feature flags.
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
+ set(CMAKE_HIP_COMPILE_OPTIONS_VISIBILITY -fvisibility=)
+
+ string(APPEND CMAKE_HIP_FLAGS_INIT " ")
+ string(APPEND CMAKE_HIP_FLAGS_DEBUG_INIT " -g")
+ string(APPEND CMAKE_HIP_FLAGS_RELEASE_INIT " -O3 -DNDEBUG")
+ string(APPEND CMAKE_HIP_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG")
+ string(APPEND CMAKE_HIP_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG")
+ endif()
+
+ set(CMAKE_SHARED_LIBRARY_CREATE_HIP_FLAGS -shared)
+ set(CMAKE_INCLUDE_SYSTEM_FLAG_HIP "-isystem ")
+
+ set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+ set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
+ set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1)
+ set(CMAKE_${lang}_RESPONSE_FILE_FLAG "@")
+ set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "@")
+endmacro()
diff --git a/Modules/Compiler/TI.cmake b/Modules/Compiler/TI.cmake
index c8c163513..0f9ded3ca 100644
--- a/Modules/Compiler/TI.cmake
+++ b/Modules/Compiler/TI.cmake
@@ -16,6 +16,10 @@ set(__COMPILER_TI_SOURCE_FLAG_ASM "--asm_file")
macro(__compiler_ti lang)
set(CMAKE_${lang}_RESPONSE_FILE_FLAG "--cmd_file=")
+ # Using --cmd_file flag is not possible after the --run_linker flag.
+ # By using a whitespace only the filename is used without flag.
+ # That file is interpreted as linker command file which may contain files to link.
+ set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG " ")
set(CMAKE_INCLUDE_FLAG_${lang} "--include_path=")
set(CMAKE_DEPFILE_FLAGS_${lang} "--preproc_with_compile --preproc_dependency=<DEP_FILE>")
@@ -29,11 +33,6 @@ macro(__compiler_ti lang)
set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> qa <TARGET> <OBJECTS>")
set(CMAKE_${lang}_ARCHIVE_FINISH "")
- # After the --run_linker flag a response file is not possible
- set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "")
- set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
- set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 0)
-
set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_${lang}_COMPILER> <FLAGS> --run_linker --output_file=<TARGET> --map_file=<TARGET_NAME>.map <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES>")
endmacro()
diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index d6fbae9aa..189374be4 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -941,14 +941,15 @@ function(_ExternalData_link_or_copy src dst)
file(RELATIVE_PATH tgt "${dst_dir}" "${src}")
endif()
endif()
- execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${tgt}" "${tmp}" RESULT_VARIABLE result)
+ # Create link (falling back to copying if there's a problem).
+ file(CREATE_LINK "${tgt}" "${tmp}" RESULT result COPY_ON_ERROR SYMBOLIC)
else()
# Create a copy.
- execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${src}" "${tmp}" RESULT_VARIABLE result)
+ file(COPY_FILE "${src}" "${tmp}" RESULT result)
endif()
if(result)
file(REMOVE "${tmp}")
- message(FATAL_ERROR "Failed to create\n ${tmp}\nfrom\n ${obj}")
+ message(FATAL_ERROR "Failed to create:\n \"${tmp}\"\nfrom:\n \"${obj}\"\nwith error:\n ${result}")
endif()
# Atomically create/replace the real destination.
@@ -1101,7 +1102,14 @@ function(_ExternalData_download_object name hash algo var_obj var_success var_er
set(success 1)
if(found)
- file(RENAME "${tmp}" "${obj}")
+ # Atomically create the object. If we lose a race with another process,
+ # do not replace it. Content-addressing ensures it has what we expect.
+ file(RENAME "${tmp}" "${obj}" NO_REPLACE RESULT result)
+ if (result STREQUAL "NO_REPLACE")
+ file(REMOVE "${tmp}")
+ elseif (result)
+ message(FATAL_ERROR "Failed to rename:\n \"${tmp}\"\nto:\n \"${obj}\"\nwith error:\n ${result}")
+ endif()
message(STATUS "Downloaded object: \"${obj}\"")
elseif(EXISTS "${staged}")
set(obj "${staged}")
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 90ed1ee63..9e25beeca 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -212,7 +212,7 @@ External Project Definition
``TLS_VERIFY <bool>``
Specifies whether certificate verification should be performed for
https URLs. If this option is not provided, the default behavior is
- determined by the ``CMAKE_TLS_VERIFY`` variable (see
+ determined by the :variable:`CMAKE_TLS_VERIFY` variable (see
:command:`file(DOWNLOAD)`). If that is also not set, certificate
verification will not be performed. In situations where ``URL_HASH``
cannot be provided, this option can be an alternative verification
@@ -456,9 +456,16 @@ External Project Definition
overridden if required.
``CONFIGURE_COMMAND <cmd>...``
- The default configure command runs CMake with options based on the main
- project. For non-CMake external projects, the ``CONFIGURE_COMMAND``
- option must be used to override this behavior
+ The default configure command runs CMake with a few options based on
+ the main project. The options added are typically only those needed to
+ use the same generator as the main project, but the ``CMAKE_GENERATOR``
+ option can be given to override this. The project is responsible for
+ adding any toolchain details, flags or other settings it wants to
+ re-use from the main project or otherwise specify (see ``CMAKE_ARGS``,
+ ``CMAKE_CACHE_ARGS`` and ``CMAKE_CACHE_DEFAULT_ARGS`` below).
+
+ For non-CMake external projects, the ``CONFIGURE_COMMAND`` option must
+ be used to override the default configure command
(:manual:`generator expressions <cmake-generator-expressions(7)>` are
supported). For projects that require no configure step, specify this
option with an empty string as the command to execute.
@@ -564,6 +571,16 @@ External Project Definition
default build step. This can be overridden with custom build commands if
required.
+ If both the main project and the external project use make as their build
+ tool, the build step of the external project is invoked as a recursive
+ make using ``$(MAKE)``. This will communicate some build tool settings
+ from the main project to the external project. If either the main project
+ or external project is not using make, no build tool settings will be
+ passed to the external project other than those established by the
+ configure step (i.e. running ``ninja -v`` in the main project will not
+ pass ``-v`` to the external project's build step, even if it also uses
+ ``ninja`` as its build tool).
+
``BUILD_COMMAND <cmd>...``
Overrides the default build command
(:manual:`generator expressions <cmake-generator-expressions(7)>` are
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index 8adef4777..bd82a90e1 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -34,7 +34,7 @@ The following shows a typical example of declaring content details:
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG release-1.8.0
+ GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)
For most typical cases, populating the content can then be done with a single
@@ -126,13 +126,13 @@ Declaring Content Details
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG release-1.8.0
+ GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)
FetchContent_Declare(
myCompanyIcons
URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz
- URL_HASH 5588a7b18261c20068beabfb4f530b87
+ URL_HASH MD5=5588a7b18261c20068beabfb4f530b87
)
FetchContent_Declare(
@@ -141,6 +141,11 @@ Declaring Content Details
SVN_REVISION -r12345
)
+ Where contents are being fetched from a remote location and you do not
+ control that server, it is advisable to use a hash for ``GIT_TAG`` rather
+ than a branch or tag name. A commit hash is more secure and helps to
+ confirm that the downloaded contents are what you expected.
+
Populating The Content
""""""""""""""""""""""
@@ -291,7 +296,7 @@ is simpler and provides additional features over the pattern above.
The ``FetchContent_Populate()`` command also supports a syntax allowing the
content details to be specified directly rather than using any saved
details. This is more low-level and use of this form is generally to be
- avoided in favour of using saved content details as outlined above.
+ avoided in favor of using saved content details as outlined above.
Nevertheless, in certain situations it can be useful to invoke the content
population as an isolated operation (typically as part of implementing some
other higher level feature or when using CMake in script mode):
@@ -456,12 +461,12 @@ frameworks are available to the main build:
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG release-1.8.0
+ GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
- GIT_TAG v2.5.0
+ GIT_TAG de6fe184a9ac1a06895cdd1c9b437f0a0bdf14ad # v2.13.4
)
# After the following call, the CMake targets defined by googletest and
@@ -480,7 +485,7 @@ it into the main build:
FetchContent_Declare(
protobuf
GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
- GIT_TAG v3.12.0
+ GIT_TAG ae50d9b9902526efd6c7a1907d09739f959c6297 # v3.15.0
SOURCE_SUBDIR cmake
)
set(protobuf_BUILD_TESTS OFF)
@@ -517,7 +522,7 @@ that all five projects are available on a company git server. The
FetchContent_Declare(
projE
GIT_REPOSITORY git@mycompany.com:git/projE.git
- GIT_TAG origin/release/2.3-rc1
+ GIT_TAG v2.3-rc1
)
# Order is important, see notes in the discussion further below
@@ -1048,7 +1053,7 @@ function(FetchContent_Populate contentName)
# Don't set global properties, or record that we did this population, since
# this was a direct call outside of the normal declared details form.
# We only want to save values in the global properties for content that
- # honours the hierarchical details mechanism so that projects are not
+ # honors the hierarchical details mechanism so that projects are not
# robbed of the ability to override details set in nested projects.
return()
endif()
@@ -1177,11 +1182,11 @@ endfunction()
# calls will be available to the caller.
macro(FetchContent_MakeAvailable)
- foreach(contentName IN ITEMS ${ARGV})
- string(TOLOWER ${contentName} contentNameLower)
- FetchContent_GetProperties(${contentName})
- if(NOT ${contentNameLower}_POPULATED)
- FetchContent_Populate(${contentName})
+ foreach(__cmake_contentName IN ITEMS ${ARGV})
+ string(TOLOWER ${__cmake_contentName} __cmake_contentNameLower)
+ FetchContent_GetProperties(${__cmake_contentName})
+ if(NOT ${__cmake_contentNameLower}_POPULATED)
+ FetchContent_Populate(${__cmake_contentName})
# Only try to call add_subdirectory() if the populated content
# can be treated that way. Protecting the call with the check
@@ -1192,22 +1197,28 @@ macro(FetchContent_MakeAvailable)
# for ExternalProject. It won't matter if it was passed through
# to the ExternalProject sub-build, since it would have been
# ignored there.
- set(__fc_srcdir "${${contentNameLower}_SOURCE_DIR}")
- __FetchContent_getSavedDetails(${contentName} contentDetails)
- if("${contentDetails}" STREQUAL "")
- message(FATAL_ERROR "No details have been set for content: ${contentName}")
+ set(__cmake_srcdir "${${__cmake_contentNameLower}_SOURCE_DIR}")
+ __FetchContent_getSavedDetails(${__cmake_contentName} __cmake_contentDetails)
+ if("${__cmake_contentDetails}" STREQUAL "")
+ message(FATAL_ERROR "No details have been set for content: ${__cmake_contentName}")
endif()
- cmake_parse_arguments(__fc_arg "" "SOURCE_SUBDIR" "" ${contentDetails})
- if(NOT "${__fc_arg_SOURCE_SUBDIR}" STREQUAL "")
- string(APPEND __fc_srcdir "/${__fc_arg_SOURCE_SUBDIR}")
+ cmake_parse_arguments(__cmake_arg "" "SOURCE_SUBDIR" "" ${__cmake_contentDetails})
+ if(NOT "${__cmake_arg_SOURCE_SUBDIR}" STREQUAL "")
+ string(APPEND __cmake_srcdir "/${__cmake_arg_SOURCE_SUBDIR}")
endif()
- if(EXISTS ${__fc_srcdir}/CMakeLists.txt)
- add_subdirectory(${__fc_srcdir} ${${contentNameLower}_BINARY_DIR})
+ if(EXISTS ${__cmake_srcdir}/CMakeLists.txt)
+ add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR})
endif()
- unset(__fc_srcdir)
+ unset(__cmake_srcdir)
endif()
endforeach()
+ # clear local variables to prevent leaking into the caller's scope
+ unset(__cmake_contentName)
+ unset(__cmake_contentNameLower)
+ unset(__cmake_contentDetails)
+ unset(__cmake_arg_SOURCE_SUBDIR)
+
endmacro()
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index b4650b2ae..726ff75bf 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -8,11 +8,11 @@ FindBLAS
Find Basic Linear Algebra Subprograms (BLAS) library
This module finds an installed Fortran library that implements the
-BLAS linear-algebra interface (see http://www.netlib.org/blas/).
+`BLAS linear-algebra interface`_.
-The approach follows that taken for the ``autoconf`` macro file,
-``acx_blas.m4`` (distributed at
-http://ac-archive.sourceforge.net/ac-archive/acx_blas.html).
+At least one of the ``C``, ``CXX``, or ``Fortran`` languages must be enabled.
+
+.. _`BLAS linear-algebra interface`: http://www.netlib.org/blas/
Input Variables
^^^^^^^^^^^^^^^
@@ -23,61 +23,8 @@ The following variables may be set to influence this module's behavior:
if ``ON`` use static linkage
``BLA_VENDOR``
- If set, checks only the specified vendor, if not set checks all the
- possibilities. List of vendors valid in this module:
-
- * ``Goto``
- * ``FlexiBLAS``
- * ``OpenBLAS``
- * ``FLAME``
- * ``ATLAS PhiPACK``
- * ``CXML``
- * ``DXML``
- * ``SunPerf``
- * ``SCSL``
- * ``SGIMATH``
- * ``IBMESSL``
- * ``Intel10_32`` (intel mkl v10 32 bit, threaded code)
- * ``Intel10_64lp`` (intel mkl v10+ 64 bit, threaded code, lp64 model)
- * ``Intel10_64lp_seq`` (intel mkl v10+ 64 bit, sequential code, lp64 model)
- * ``Intel10_64ilp`` (intel mkl v10+ 64 bit, threaded code, ilp64 model)
- * ``Intel10_64ilp_seq`` (intel mkl v10+ 64 bit, sequential code, ilp64 model)
- * ``Intel10_64_dyn`` (intel mkl v10+ 64 bit, single dynamic library)
- * ``Intel`` (obsolete versions of mkl 32 and 64 bit)
- * ``ACML``
- * ``ACML_MP``
- * ``ACML_GPU``
- * ``Apple``
- * ``NAS``
- * ``Arm``
- * ``Arm_mp``
- * ``Arm_ilp64``
- * ``Arm_ilp64_mp``
- * ``EML``
- * ``EML_mt``
- * ``Generic``
-
- .. versionadded:: 3.6
- ``OpenBLAS`` support.
-
- .. versionadded:: 3.11
- ``FLAME`` support.
-
- .. versionadded:: 3.13
- Added ILP64 MKL variants (``Intel10_64ilp``, ``Intel10_64ilp_seq``).
-
- .. versionadded:: 3.17
- Added single dynamic library MKL variant (``Intel10_64_dyn``).
-
- .. versionadded:: 3.18
- Arm Performance Libraries support (``Arm``, ``Arm_mp``, ``Arm_ilp64``,
- ``Arm_ilp64_mp``).
-
- .. versionadded:: 3.19
- ``FlexiBLAS`` support.
-
- .. versionadded:: 3.20
- Elbrus Math Library support (``EML``, ``EML_mt``).
+ Set to one of the :ref:`BLAS/LAPACK Vendors` to search for BLAS only
+ from the specified vendor. If not set, all vendors are considered.
``BLA_F95``
if ``ON`` tries to find the BLAS95 interfaces
@@ -91,13 +38,12 @@ The following variables may be set to influence this module's behavior:
Imported targets
^^^^^^^^^^^^^^^^
-.. versionadded:: 3.18
-
-This module defines the following :prop_tgt:`IMPORTED` target:
+This module defines the following :prop_tgt:`IMPORTED` targets:
``BLAS::BLAS``
- The libraries to use for BLAS, if found.
+ .. versionadded:: 3.18
+ The libraries to use for BLAS, if found.
Result Variables
^^^^^^^^^^^^^^^^
@@ -117,31 +63,168 @@ This module defines the following variables:
``BLAS95_FOUND``
library implementing the BLAS95 interface is found
-.. note::
+.. _`BLAS/LAPACK Vendors`:
+
+BLAS/LAPACK Vendors
+^^^^^^^^^^^^^^^^^^^
+
+``Generic``
+ Generic reference implementation
+
+``ACML``, ``ACML_MP``, ``ACML_GPU``
+ AMD Core Math Library
+
+``Apple``, ``NAS``
+ Apple BLAS (Accelerate), and Apple NAS (vecLib)
+
+``Arm``, ``Arm_mp``, ``Arm_ilp64``, ``Arm_ilp64_mp``
+ .. versionadded:: 3.18
+
+ Arm Performance Libraries
+
+``ATLAS``
+ Automatically Tuned Linear Algebra Software
+
+``CXML``, ``DXML``
+ Compaq/Digital Extended Math Library
+
+``EML``, ``EML_mt``
+ .. versionadded:: 3.20
+
+ Elbrus Math Library
+
+``FLAME``
+ .. versionadded:: 3.11
+
+ BLIS Framework
+
+``FlexiBLAS``
+ .. versionadded:: 3.19
+
+``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``
+ .. versionadded:: 3.20
+
+ Fujitsu SSL2 serial and parallel blas/lapack
+
+``Goto``
+ GotoBLAS
+
+``IBMESSL``
+ IBM Engineering and Scientific Subroutine Library
+
+``Intel``
+ Intel MKL 32 bit and 64 bit obsolete versions
+
+``Intel10_32``
+ Intel MKL v10 32 bit, threaded code
+
+``Intel10_64lp``
+ Intel MKL v10+ 64 bit, threaded code, lp64 model
+
+``Intel10_64lp_seq``
+ Intel MKL v10+ 64 bit, sequential code, lp64 model
+
+``Intel10_64ilp``
+ .. versionadded:: 3.13
+
+ Intel MKL v10+ 64 bit, threaded code, ilp64 model
+
+``Intel10_64ilp_seq``
+ .. versionadded:: 3.13
+
+ Intel MKL v10+ 64 bit, sequential code, ilp64 model
+
+``Intel10_64_dyn``
+ .. versionadded:: 3.17
+
+ Intel MKL v10+ 64 bit, single dynamic library
+
+``NVHPC``
+ .. versionadded:: 3.21
+
+ NVIDIA HPC SDK
+
+``OpenBLAS``
+ .. versionadded:: 3.6
+
+``PhiPACK``
+ Portable High Performance ANSI C (PHiPAC)
+
+``SCSL``
+ Scientific Computing Software Library
- C, CXX or Fortran must be enabled to detect a BLAS library.
- C or CXX must be enabled to use Intel Math Kernel Library (MKL).
+``SGIMATH``
+ SGI Scientific Mathematical Library
- For example, to use Intel MKL libraries and/or Intel compiler:
+``SunPerf``
+ Sun Performance Library
- .. code-block:: cmake
+.. _`Intel MKL`:
- set(BLA_VENDOR Intel10_64lp)
- find_package(BLAS)
+Intel MKL
+^^^^^^^^^
-Hints
-^^^^^
+To use the Intel MKL implementation of BLAS, a project must enable at least
+one of the ``C`` or ``CXX`` languages. Set ``BLA_VENDOR`` to an Intel MKL
+variant either on the command-line as ``-DBLA_VENDOR=Intel10_64lp`` or in
+project code:
-``MKLROOT``
- .. versionadded:: 3.15
+.. code-block:: cmake
- Set this environment variable to a directory that contains an MKL
- installation, or add the directory to the dynamic library loader environment
- variable for your platform (``LIB``, ``DYLD_LIBRARY_PATH`` or
- ``LD_LIBRARY_PATH``).
+ set(BLA_VENDOR Intel10_64lp)
+ find_package(BLAS)
+
+In order to build a project using Intel MKL, and end user must first
+establish an Intel MKL environment:
+
+Intel oneAPI
+ Source the full Intel environment script:
+
+ .. code-block:: shell
+
+ . /opt/intel/oneapi/setvars.sh
+
+ Or, source the MKL component environment script:
+
+ .. code-block:: shell
+
+ . /opt/intel/oneapi/mkl/latest/env/vars.sh
+
+Intel Classic
+ Source the full Intel environment script:
+
+ .. code-block:: shell
+
+ . /opt/intel/bin/compilervars.sh intel64
+
+ Or, source the MKL component environment script:
+
+ .. code-block:: shell
+
+ . /opt/intel/mkl/bin/mklvars.sh intel64
+
+The above environment scripts set the ``MKLROOT`` environment variable
+to the top of the MKL installation. They also add the location of the
+runtime libraries to the dynamic library loader environment variable for
+your platform (e.g. ``LD_LIBRARY_PATH``). This is necessary for programs
+linked against MKL to run.
+
+.. note::
+
+ As of Intel oneAPI 2021.2, loading only the MKL component does not
+ make all of its dependencies available. In particular, the ``iomp5``
+ library must be available separately, or provided by also loading
+ the compiler component environment:
+
+ .. code-block:: shell
+
+ . /opt/intel/oneapi/compiler/latest/env/vars.sh
#]=======================================================================]
+# The approach follows that of the ``autoconf`` macro file, ``acx_blas.m4``
+# (distributed at http://ac-archive.sourceforge.net/ac-archive/acx_blas.html).
+
# Check the language being used
if(NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED))
if(BLAS_FIND_REQUIRED)
@@ -153,13 +236,18 @@ if(NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_CO
endif()
function(_add_blas_target)
- if(NOT TARGET BLAS::BLAS)
+ if(BLAS_FOUND AND NOT TARGET BLAS::BLAS)
add_library(BLAS::BLAS INTERFACE IMPORTED)
if(BLAS_LIBRARIES)
set_target_properties(BLAS::BLAS PROPERTIES
INTERFACE_LINK_LIBRARIES "${BLAS_LIBRARIES}"
)
endif()
+ if(BLAS_LINKER_FLAGS)
+ set_target_properties(BLAS::BLAS PROPERTIES
+ INTERFACE_LINK_OPTIONS "${BLAS_LINKER_FLAGS}"
+ )
+ endif()
endif()
endfunction()
@@ -168,10 +256,7 @@ if(CMAKE_Fortran_COMPILER_LOADED)
else()
include(${CMAKE_CURRENT_LIST_DIR}/CheckFunctionExists.cmake)
endif()
-include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-cmake_push_check_state()
-set(CMAKE_REQUIRED_QUIET ${BLAS_FIND_QUIETLY})
if(BLA_PREFER_PKGCONFIG)
find_package(PkgConfig)
@@ -184,40 +269,33 @@ if(BLA_PREFER_PKGCONFIG)
endif()
endif()
-set(_blas_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
-if(BLA_STATIC)
- if(WIN32)
- set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
- else()
- set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
- endif()
-else()
- if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
- # for ubuntu's libblas3gf and liblapack3gf packages
- set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf)
- endif()
-endif()
-
# TODO: move this stuff to a separate module
-macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _addlibdir _subdirs)
- # This macro checks for the existence of the combination of fortran libraries
- # given by _list. If the combination is found, this macro checks (using the
- # Check_Fortran_Function_Exists macro) whether can link against that library
- # combination using the name of a routine given by _name using the linker
- # flags given by _flags. If the combination of libraries is found and passes
- # the link test, LIBRARIES is set to the list of complete library paths that
- # have been found. Otherwise, LIBRARIES is set to FALSE.
-
- # N.B. _prefix is the prefix applied to the names of all cached variables that
- # are generated internally and marked advanced by this macro.
- # _addlibdir is a list of additional search paths. _subdirs is a list of path
- # suffixes to be used by find_library().
+function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs)
+ # This function checks for the existence of the combination of libraries
+ # given by _list. If the combination is found, this checks whether can link
+ # against that library combination using the name of a routine given by _name
+ # using the linker flags given by _flags. If the combination of libraries is
+ # found and passes the link test, ${LIBRARIES} is set to the list of complete
+ # library paths that have been found. Otherwise, ${LIBRARIES} is set to FALSE.
set(_libraries_work TRUE)
- set(${LIBRARIES})
+ set(_libraries)
set(_combined_name)
+ if(BLA_STATIC)
+ if(WIN32)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ else()
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ endif()
+ else()
+ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ # for ubuntu's libblas3gf and liblapack3gf packages
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf)
+ endif()
+ endif()
+
set(_extaddlibdir "${_addlibdir}")
if(WIN32)
list(APPEND _extaddlibdir ENV LIB)
@@ -229,33 +307,37 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add
list(APPEND _extaddlibdir "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}")
foreach(_library ${_list})
- if(_library MATCHES "^-Wl,--(start|end)-group$")
- # Respect linker flags like --start/end-group (required by MKL)
- set(${LIBRARIES} ${${LIBRARIES}} "${_library}")
+ if(_library MATCHES "^-")
+ # Respect linker flags as-is (required by MKL)
+ list(APPEND _libraries "${_library}")
else()
- set(_combined_name ${_combined_name}_${_library})
- if(NOT "${_threadlibs}" STREQUAL "")
- set(_combined_name ${_combined_name}_threadlibs)
+ string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}")
+ set(_combined_name ${_combined_name}_${_lib_var})
+ if(NOT "${_deps}" STREQUAL "")
+ set(_combined_name ${_combined_name}_deps)
endif()
if(_libraries_work)
- find_library(${_prefix}_${_library}_LIBRARY
+ find_library(${_prefix}_${_lib_var}_LIBRARY
NAMES ${_library}
NAMES_PER_DIR
PATHS ${_extaddlibdir}
PATH_SUFFIXES ${_subdirs}
)
- #message("DEBUG: find_library(${_library}) got ${${_prefix}_${_library}_LIBRARY}")
- mark_as_advanced(${_prefix}_${_library}_LIBRARY)
- set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
- set(_libraries_work ${${_prefix}_${_library}_LIBRARY})
+ mark_as_advanced(${_prefix}_${_lib_var}_LIBRARY)
+ list(APPEND _libraries ${${_prefix}_${_lib_var}_LIBRARY})
+ set(_libraries_work ${${_prefix}_${_lib_var}_LIBRARY})
endif()
endif()
endforeach()
+ foreach(_flag ${_flags})
+ string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}")
+ set(_combined_name ${_combined_name}_${_flag_var})
+ endforeach()
if(_libraries_work)
# Test this combination of libraries.
- set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_threadlibs})
- #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}")
+ set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${_libraries} ${_deps})
+ set(CMAKE_REQUIRED_QUIET ${BLAS_FIND_QUIETLY})
if(CMAKE_Fortran_COMPILER_LOADED)
check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS)
else()
@@ -267,19 +349,20 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add
if(_libraries_work)
if("${_list}" STREQUAL "")
- set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
+ set(_libraries "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
else()
- set(${LIBRARIES} ${${LIBRARIES}} ${_threadlibs})
+ list(APPEND _libraries ${_deps})
endif()
else()
- set(${LIBRARIES} FALSE)
+ set(_libraries FALSE)
endif()
- #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}")
-endmacro()
+ set(${LIBRARIES} "${_libraries}" PARENT_SCOPE)
+endfunction()
set(BLAS_LINKER_FLAGS)
set(BLAS_LIBRARIES)
set(BLAS95_LIBRARIES)
+set(_blas_fphsa_req_var BLAS_LIBRARIES)
if(NOT $ENV{BLA_VENDOR} STREQUAL "")
set(BLA_VENDOR $ENV{BLA_VENDOR})
else()
@@ -302,6 +385,9 @@ if(BLA_VENDOR STREQUAL "All")
""
)
endif()
+ if(BLAS_WORKS)
+ set(_blas_fphsa_req_var BLAS_WORKS)
+ endif()
endif()
# BLAS in the Intel MKL 10+ library?
@@ -523,7 +609,9 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
"compiler/lib/${BLAS_mkl_ARCH_NAME}"
"mkl/lib" "mkl/lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}"
"mkl/lib/${BLAS_mkl_ARCH_NAME}"
- "lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}")
+ "lib" "lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}"
+ "lib/${BLAS_mkl_ARCH_NAME}"
+ )
foreach(IT ${BLAS_SEARCH_LIBS})
string(REPLACE " " ";" SEARCH_LIBS ${IT})
@@ -619,8 +707,6 @@ if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All")
endif()
set(_threadlibs "${CMAKE_THREAD_LIBS_INIT}")
if(BLA_STATIC)
- set(_blas_STATIC_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}")
- set(CMAKE_FIND_LIBRARY_SUFFIXES "${_blas_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}")
if (CMAKE_C_COMPILER_LOADED)
find_package(OpenMP COMPONENTS C)
list(PREPEND _threadlibs "${OpenMP_C_LIBRARIES}")
@@ -628,8 +714,6 @@ if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All")
find_package(OpenMP COMPONENTS CXX)
list(PREPEND _threadlibs "${OpenMP_CXX_LIBRARIES}")
endif()
- set(CMAKE_FIND_LIBRARY_SUFFIXES "${_blas_STATIC_CMAKE_FIND_LIBRARY_SUFFIXES}")
- unset(_blas_STATIC_CMAKE_FIND_LIBRARY_SUFFIXES)
endif()
check_blas_libraries(
BLAS_LIBRARIES
@@ -1025,8 +1109,35 @@ if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All")
endif()
+# Fujitsu SSL2 Library?
+if(NOT BLAS_LIBRARIES
+ AND (BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All"))
+ if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP")
+ set(_ssl2_suffix BLAMP)
+ else()
+ set(_ssl2_suffix)
+ endif()
+ check_blas_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ "-SSL2${_ssl2_suffix}"
+ ""
+ ""
+ ""
+ ""
+ )
+ if(BLAS_LIBRARIES)
+ set(BLAS_LINKER_FLAGS "-SSL2${_ssl2_suffix}")
+ set(_blas_fphsa_req_var BLAS_LINKER_FLAGS)
+ endif()
+ unset(_ssl2_suffix)
+endif()
+
# Generic BLAS library?
-if(BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All")
+if(BLA_VENDOR STREQUAL "Generic" OR
+ BLA_VENDOR STREQUAL "NVHPC" OR
+ BLA_VENDOR STREQUAL "All")
if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
@@ -1041,17 +1152,14 @@ if(BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All")
endif()
endif()
-if(NOT BLA_F95)
- find_package_handle_standard_args(BLAS REQUIRED_VARS BLAS_LIBRARIES)
-endif()
-
-
-# On compilers that implicitly link BLAS (such as ftn, cc, and CC on Cray HPC machines)
-# we used a placeholder for empty BLAS_LIBRARIES to get through our logic above.
+# On compilers that implicitly link BLAS (i.e. CrayPrgEnv) we used a
+# placeholder for empty BLAS_LIBRARIES to get through our logic above.
if(BLAS_LIBRARIES STREQUAL "BLAS_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
set(BLAS_LIBRARIES "")
endif()
+if(NOT BLA_F95)
+ find_package_handle_standard_args(BLAS REQUIRED_VARS ${_blas_fphsa_req_var})
+endif()
+
_add_blas_target()
-cmake_pop_check_state()
-set(CMAKE_FIND_LIBRARY_SUFFIXES ${_blas_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index df997e1b4..f7605c4fd 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -189,7 +189,7 @@ This module defines the following :prop_tgt:`IMPORTED` targets:
(adds ``-DBOOST_ALL_NO_LIB``).
``Boost::dynamic_linking``
- Interface target to enable dynamic linking linking with MSVC
+ Interface target to enable dynamic linking with MSVC
(adds ``-DBOOST_ALL_DYN_LINK``).
Implicit dependencies such as ``Boost::filesystem`` requiring
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index 16d75711b..dd795f449 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -2,19 +2,19 @@
FindCUDA
--------
-.. deprecated:: 3.10
+.. warning:: *Deprecated since version 3.10.*
It is no longer necessary to use this module or call ``find_package(CUDA)``
for compiling CUDA code. Instead, list ``CUDA`` among the languages named
in the top-level call to the :command:`project` command, or call the
:command:`enable_language` command with ``CUDA``.
-Then one can add CUDA (``.cu``) sources to programs directly
-in calls to :command:`add_library` and :command:`add_executable`.
+Then one can add CUDA (``.cu``) sources directly to targets similar to other
+languages.
.. versionadded:: 3.17
- To find and use the CUDA toolkit libraries the :module:`FindCUDAToolkit`
- module has superseded this module. It works whether or not the ``CUDA``
- language is enabled.
+ To find and use the CUDA toolkit libraries manually, use the
+ :module:`FindCUDAToolkit` module instead. It works regardless of the
+ ``CUDA`` language being enabled.
Documentation of Deprecated Usage
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake
index 8801cb1bf..89b8c997c 100644
--- a/Modules/FindCUDAToolkit.cmake
+++ b/Modules/FindCUDAToolkit.cmake
@@ -75,12 +75,17 @@ The CUDA Toolkit search behavior uses the following order:
(2) ensure that the correct ``nvcc`` executable shows up in ``$PATH`` for
:command:`find_program` to find.
+Arguments
+^^^^^^^^^
+
+``[<version>]``
+ The ``[<version>]`` argument requests a version with which the package found
+ should be compatible. See :ref:`find_package version format <FIND_PACKAGE_VERSION_FORMAT>`
+ for more details.
+
Options
^^^^^^^
-``VERSION``
- If specified, describes the version of the CUDA Toolkit to search for.
-
``REQUIRED``
If specified, configuration will error if a suitable CUDA Toolkit is not
found.
@@ -410,7 +415,7 @@ Result variables
``CUDAToolkit_VERSION_MAJOR``
The major version of the CUDA Toolkit.
-``CUDAToolkit_VERSION_MAJOR``
+``CUDAToolkit_VERSION_MINOR``
The minor version of the CUDA Toolkit.
``CUDAToolkit_VERSION_PATCH``
diff --git a/Modules/FindCurses.cmake b/Modules/FindCurses.cmake
index 5e25deb68..bfa1d6fb4 100644
--- a/Modules/FindCurses.cmake
+++ b/Modules/FindCurses.cmake
@@ -76,7 +76,7 @@ endif()
# cygwin ncurses stopped providing curses.h symlinks see above
# message. Cygwin is an ncurses package, so force ncurses on
# cygwin if the curses.h is missing
-if(CYGWIN)
+if(CURSES_NCURSES_LIBRARY AND CYGWIN)
if (CURSES_NEED_WIDE)
if(NOT EXISTS /usr/include/ncursesw/curses.h)
set(CURSES_USE_NCURSES TRUE)
diff --git a/Modules/FindDevIL.cmake b/Modules/FindDevIL.cmake
index 998494365..c8e5e3154 100644
--- a/Modules/FindDevIL.cmake
+++ b/Modules/FindDevIL.cmake
@@ -10,26 +10,57 @@ FindDevIL
This module locates the developer's image library.
http://openil.sourceforge.net/
+IMPORTED Targets
+^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.21
+
+This module defines the :prop_tgt:`IMPORTED` targets:
+
+``DevIL::IL``
+ Defined if the system has DevIL.
+
+``DevIL::ILU``
+ Defined if the system has DevIL Utilities.
+
+``DevIL::ILUT``
+ Defined if the system has DevIL Utility Toolkit.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
This module sets:
-::
-
- IL_LIBRARIES - the name of the IL library. These include the full path to
- the core DevIL library. This one has to be linked into the
- application.
- ILU_LIBRARIES - the name of the ILU library. Again, the full path. This
- library is for filters and effects, not actual loading. It
- doesn't have to be linked if the functionality it provides
- is not used.
- ILUT_LIBRARIES - the name of the ILUT library. Full path. This part of the
- library interfaces with OpenGL. It is not strictly needed
- in applications.
- IL_INCLUDE_DIR - where to find the il.h, ilu.h and ilut.h files.
- DevIL_FOUND - this is set to TRUE if all the above variables were set.
- This will be set to false if ILU or ILUT are not found,
- even if they are not needed. In most systems, if one
- library is found all the others are as well. That's the
- way the DevIL developers release it.
+``IL_LIBRARIES``
+ The name of the IL library. These include the full path to
+ the core DevIL library. This one has to be linked into the
+ application.
+
+``ILU_LIBRARIES``
+ The name of the ILU library. Again, the full path. This
+ library is for filters and effects, not actual loading. It
+ doesn't have to be linked if the functionality it provides
+ is not used.
+
+``ILUT_LIBRARIES``
+ The name of the ILUT library. Full path. This part of the
+ library interfaces with OpenGL. It is not strictly needed
+ in applications.
+
+``IL_INCLUDE_DIR``
+ where to find the il.h, ilu.h and ilut.h files.
+
+``DevIL_FOUND``
+ This is set to TRUE if all the above variables were set.
+ This will be set to false if ILU or ILUT are not found,
+ even if they are not needed. In most systems, if one
+ library is found all the others are as well. That's the
+ way the DevIL developers release it.
+
+``DevIL_ILUT_FOUND``
+ .. versionadded:: 3.21
+
+ This is set to TRUE if the ILUT library is found.
#]=======================================================================]
# TODO: Add version support.
@@ -73,3 +104,36 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(DevIL DEFAULT_MSG
IL_INCLUDE_DIR)
# provide legacy variable for compatibility
set(IL_FOUND ${DevIL_FOUND})
+
+# create imported targets ONLY if we found DevIL.
+if(DevIL_FOUND)
+ # Report the ILUT found if ILUT_LIBRARIES contains valid path.
+ if (ILUT_LIBRARIES)
+ set(DevIL_ILUT_FOUND TRUE)
+ else()
+ set(DevIL_ILUT_FOUND FALSE)
+ endif()
+
+ if(NOT TARGET DevIL::IL)
+ add_library(DevIL::IL UNKNOWN IMPORTED)
+ set_target_properties(DevIL::IL PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${IL_INCLUDE_DIR}"
+ IMPORTED_LOCATION "${IL_LIBRARIES}")
+ endif()
+
+ # DevIL Utilities target
+ if(NOT TARGET DevIL::ILU)
+ add_library(DevIL::ILU UNKNOWN IMPORTED)
+ set_target_properties(DevIL::ILU PROPERTIES
+ IMPORTED_LOCATION "${ILU_LIBRARIES}")
+ target_link_libraries(DevIL::ILU INTERFACE DevIL::IL)
+ endif()
+
+ # ILUT (if found)
+ if(NOT TARGET DevIL::ILUT AND DevIL_ILUT_FOUND)
+ add_library(DevIL::ILUT UNKNOWN IMPORTED)
+ set_target_properties(DevIL::ILUT PROPERTIES
+ IMPORTED_LOCATION "${ILUT_LIBRARIES}")
+ target_link_libraries(DevIL::ILUT INTERFACE DevIL::ILU)
+ endif()
+endif()
diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake
index bbf941efb..4a16e316a 100644
--- a/Modules/FindDoxygen.cmake
+++ b/Modules/FindDoxygen.cmake
@@ -223,7 +223,8 @@ them to be separated by whitespace. CMake variables hold lists as a string with
items separated by semi-colons, so a conversion needs to be performed. The
``doxygen_add_docs()`` command specifically checks the following Doxygen config
options and will convert their associated CMake variable's contents into the
-required form if set.
+required form if set. CMake variables are named ``DOXYGEN_<name>`` for the
+Doxygen settings specified here.
::
@@ -395,6 +396,7 @@ Deprecated Hint Variables
#]=======================================================================]
cmake_policy(PUSH)
+cmake_policy(SET CMP0054 NEW) # quoted if arguments
cmake_policy(SET CMP0057 NEW) # if IN_LIST
# For backwards compatibility support
diff --git a/Modules/FindFLTK.cmake b/Modules/FindFLTK.cmake
index e1e239a66..bab72560d 100644
--- a/Modules/FindFLTK.cmake
+++ b/Modules/FindFLTK.cmake
@@ -108,7 +108,7 @@ if(APPLE)
set( FLTK_PLATFORM_DEPENDENT_LIBS "-framework Carbon -framework Cocoa -framework ApplicationServices -lz")
endif()
-# If FLTK_INCLUDE_DIR is already defined we assigne its value to FLTK_DIR
+# If FLTK_INCLUDE_DIR is already defined we assign its value to FLTK_DIR.
if(FLTK_INCLUDE_DIR)
set(FLTK_DIR ${FLTK_INCLUDE_DIR})
endif()
diff --git a/Modules/FindGettext.cmake b/Modules/FindGettext.cmake
index 252f2aea2..99e2887e9 100644
--- a/Modules/FindGettext.cmake
+++ b/Modules/FindGettext.cmake
@@ -39,7 +39,7 @@ LANGUAGES <lang1> <lang2> ... )
If INSTALL_DESTINATION is given then automatically install rules will
be created, the language subdirectory will be taken into account
(by default use share/locale/).
- If ALL is specified, the pot file is processed when building the all traget.
+ If ALL is specified, the pot file is processed when building the all target.
It creates a custom target "potfile".
GETTEXT_PROCESS_PO_FILES( <lang> [ALL] [INSTALL_DESTINATION <dir>]
@@ -51,7 +51,7 @@ PO_FILES <po1> <po2> ... )
If INSTALL_DESTINATION is given then automatically install rules will
be created, the language subdirectory will be taken into account
(by default use share/locale/).
- If ALL is specified, the po files are processed when building the all traget.
+ If ALL is specified, the po files are processed when building the all target.
It creates a custom target "pofiles".
.. versionadded:: 3.2
diff --git a/Modules/FindGnuplot.cmake b/Modules/FindGnuplot.cmake
index ca2467d68..b4ea6ab3f 100644
--- a/Modules/FindGnuplot.cmake
+++ b/Modules/FindGnuplot.cmake
@@ -23,6 +23,7 @@ GNUPLOT_VERSION_STRING will not work for old versions like 3.7.1.
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake)
find_program(GNUPLOT_EXECUTABLE
NAMES
@@ -31,6 +32,7 @@ find_program(GNUPLOT_EXECUTABLE
wgnupl32
PATHS
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
if (GNUPLOT_EXECUTABLE)
diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake
index ec5ebdd66..e33535513 100644
--- a/Modules/FindHDF5.cmake
+++ b/Modules/FindHDF5.cmake
@@ -811,25 +811,8 @@ if( NOT HDF5_FOUND )
endif()
foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS)
- # find the HDF5 include directories
- if("${_lang}" STREQUAL "Fortran")
- set(HDF5_INCLUDE_FILENAME hdf5.mod HDF5.mod)
- elseif("${_lang}" STREQUAL "CXX")
- set(HDF5_INCLUDE_FILENAME H5Cpp.h)
- else()
- set(HDF5_INCLUDE_FILENAME hdf5.h)
- endif()
-
- find_path(HDF5_${_lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME}
- HINTS ${HDF5_ROOT}
- PATHS $ENV{HOME}/.local/include
- PATH_SUFFIXES include Include ${_inc_suffixes} ${_lib_suffixes}
- ${_HDF5_SEARCH_OPTS}
- )
- mark_as_advanced(HDF5_${_lang}_INCLUDE_DIR)
- # set the _DIRS variable as this is what the user will normally use
- set(HDF5_${_lang}_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR})
- list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR})
+ # The "main" library.
+ set(_hdf5_main_library "")
# find the HDF5 libraries
foreach(LIB IN LISTS HDF5_${_lang}_LIBRARY_NAMES)
@@ -861,6 +844,15 @@ if( NOT HDF5_FOUND )
${_HDF5_SEARCH_OPTS}
)
+ # Set the "main" library if not already set.
+ if (NOT _hdf5_main_library)
+ if (HDF5_${LIB}_LIBRARY_RELEASE)
+ set(_hdf5_main_library "${HDF5_${LIB}_LIBRARY_RELEASE}")
+ elseif (HDF5_${LIB}_LIBRARY_DEBUG)
+ set(_hdf5_main_library "${HDF5_${LIB}_LIBRARY_DEBUG}")
+ endif ()
+ endif ()
+
select_library_configurations( HDF5_${LIB} )
list(APPEND HDF5_${_lang}_LIBRARIES ${HDF5_${LIB}_LIBRARY})
endforeach()
@@ -872,6 +864,43 @@ if( NOT HDF5_FOUND )
# required libraries.
list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_LIBRARIES})
+ # find the HDF5 include directories
+ set(_hdf5_inc_extra_paths)
+ set(_hdf5_inc_extra_suffixes)
+ if("${_lang}" STREQUAL "Fortran")
+ set(HDF5_INCLUDE_FILENAME hdf5.mod HDF5.mod)
+
+ # Add library-based search paths for Fortran modules.
+ if (NOT _hdf5_main_library STREQUAL "")
+ # gfortran module directory
+ if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
+ get_filename_component(_hdf5_library_dir "${_hdf5_main_library}" DIRECTORY)
+ list(APPEND _hdf5_inc_extra_paths "${_hdf5_library_dir}")
+ unset(_hdf5_library_dir)
+ list(APPEND _hdf5_inc_extra_suffixes gfortran/modules)
+ endif ()
+ endif ()
+ elseif("${_lang}" STREQUAL "CXX")
+ set(HDF5_INCLUDE_FILENAME H5Cpp.h)
+ else()
+ set(HDF5_INCLUDE_FILENAME hdf5.h)
+ endif()
+
+ unset(_hdf5_main_library)
+
+ find_path(HDF5_${_lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME}
+ HINTS ${HDF5_ROOT}
+ PATHS $ENV{HOME}/.local/include ${_hdf5_inc_extra_paths}
+ PATH_SUFFIXES include Include ${_inc_suffixes} ${_lib_suffixes} ${_hdf5_inc_extra_suffixes}
+ ${_HDF5_SEARCH_OPTS}
+ )
+ mark_as_advanced(HDF5_${_lang}_INCLUDE_DIR)
+ unset(_hdf5_inc_extra_paths)
+ unset(_hdf5_inc_extra_suffixes)
+ # set the _DIRS variable as this is what the user will normally use
+ set(HDF5_${_lang}_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR})
+ list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR})
+
if(HDF5_FIND_HL)
foreach(LIB IN LISTS HDF5_${_lang}_HL_LIBRARY_NAMES)
if(HDF5_USE_STATIC_LIBRARIES)
diff --git a/Modules/FindIconv.cmake b/Modules/FindIconv.cmake
index 41b75509f..566330f40 100644
--- a/Modules/FindIconv.cmake
+++ b/Modules/FindIconv.cmake
@@ -25,6 +25,24 @@ The following variables are provided to indicate iconv support:
The iconv libraries to be linked.
+.. variable:: Iconv_VERSION
+
+ .. versionadded:: 3.21
+
+ The version of iconv found (x.y)
+
+.. variable:: Iconv_VERSION_MAJOR
+
+ .. versionadded:: 3.21
+
+ The major version of iconv
+
+.. variable:: Iconv_VERSION_MINOR
+
+ .. versionadded:: 3.21
+
+ The minor version of iconv
+
.. variable:: Iconv_IS_BUILT_IN
A variable indicating whether iconv support is stemming from the
@@ -51,6 +69,10 @@ The following cache variables may also be set:
On POSIX platforms, iconv might be part of the C library and the cache
variables ``Iconv_INCLUDE_DIR`` and ``Iconv_LIBRARY`` might be empty.
+.. note::
+ Some libiconv implementations don't embed the version number in their header files.
+ In this case the variables ``Iconv_VERSION*`` will be empty.
+
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake)
@@ -100,37 +122,61 @@ if(NOT DEFINED Iconv_IS_BUILT_IN)
endif()
endif()
-if(NOT Iconv_IS_BUILT_IN)
+set(_Iconv_REQUIRED_VARS)
+if(Iconv_IS_BUILT_IN)
+ set(_Iconv_REQUIRED_VARS _Iconv_IS_BUILT_IN_MSG)
+ set(_Iconv_IS_BUILT_IN_MSG "built in to C library")
+else()
+ set(_Iconv_REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR)
+
find_path(Iconv_INCLUDE_DIR
NAMES "iconv.h"
DOC "iconv include directory")
set(Iconv_LIBRARY_NAMES "iconv" "libiconv")
-else()
- set(Iconv_INCLUDE_DIR "" CACHE FILEPATH "iconv include directory")
- set(Iconv_LIBRARY_NAMES "c")
+ mark_as_advanced(Iconv_INCLUDE_DIR)
+
+ find_library(Iconv_LIBRARY
+ NAMES iconv libiconv
+ NAMES_PER_DIR
+ DOC "iconv library (if not in the C library)")
+ mark_as_advanced(Iconv_LIBRARY)
endif()
-find_library(Iconv_LIBRARY
- NAMES ${Iconv_LIBRARY_NAMES}
- NAMES_PER_DIR
- DOC "iconv library (potentially the C library)")
+# NOTE: glibc's iconv.h does not define _LIBICONV_VERSION
+if(Iconv_INCLUDE_DIR AND EXISTS "${Iconv_INCLUDE_DIR}/iconv.h")
+ file(STRINGS ${Iconv_INCLUDE_DIR}/iconv.h Iconv_VERSION_DEFINE REGEX "_LIBICONV_VERSION (.*)")
-mark_as_advanced(Iconv_INCLUDE_DIR)
-mark_as_advanced(Iconv_LIBRARY)
+ if(Iconv_VERSION_DEFINE MATCHES "(0x[A-Fa-f0-9]+)")
+ set(Iconv_VERSION_NUMBER "${CMAKE_MATCH_1}")
+ # encoding -> version number: (major<<8) + minor
+ math(EXPR Iconv_VERSION_MAJOR "${Iconv_VERSION_NUMBER} >> 8" OUTPUT_FORMAT HEXADECIMAL)
+ math(EXPR Iconv_VERSION_MINOR "${Iconv_VERSION_NUMBER} - (${Iconv_VERSION_MAJOR} << 8)" OUTPUT_FORMAT HEXADECIMAL)
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-if(NOT Iconv_IS_BUILT_IN)
- find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR)
-else()
- find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY)
+ math(EXPR Iconv_VERSION_MAJOR "${Iconv_VERSION_MAJOR}" OUTPUT_FORMAT DECIMAL)
+ math(EXPR Iconv_VERSION_MINOR "${Iconv_VERSION_MINOR}" OUTPUT_FORMAT DECIMAL)
+ set(Iconv_VERSION "${Iconv_VERSION_MAJOR}.${Iconv_VERSION_MINOR}")
+ endif()
+
+ unset(Iconv_VERSION_DEFINE)
+ unset(Iconv_VERSION_NUMBER)
endif()
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(Iconv
+ REQUIRED_VARS ${_Iconv_REQUIRED_VARS}
+ VERSION_VAR Iconv_VERSION)
+
if(Iconv_FOUND)
- set(Iconv_INCLUDE_DIRS "${Iconv_INCLUDE_DIR}")
- set(Iconv_LIBRARIES "${Iconv_LIBRARY}")
+ if(Iconv_IS_BUILT_IN)
+ set(Iconv_INCLUDE_DIRS "")
+ set(Iconv_LIBRARIES "")
+ else()
+ set(Iconv_INCLUDE_DIRS "${Iconv_INCLUDE_DIR}")
+ set(Iconv_LIBRARIES "${Iconv_LIBRARY}")
+ endif()
if(NOT TARGET Iconv::Iconv)
add_library(Iconv::Iconv INTERFACE IMPORTED)
+ set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Iconv_INCLUDE_DIRS}")
+ set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_LINK_LIBRARIES "${Iconv_LIBRARIES}")
endif()
- set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Iconv_INCLUDE_DIRS}")
- set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_LINK_LIBRARIES "${Iconv_LIBRARIES}")
endif()
diff --git a/Modules/FindIntl.cmake b/Modules/FindIntl.cmake
index 43398c16e..95eeabda8 100644
--- a/Modules/FindIntl.cmake
+++ b/Modules/FindIntl.cmake
@@ -24,6 +24,30 @@ installation in several variables.
The intl libraries to be linked.
+.. variable:: Intl_VERSION
+
+ .. versionadded:: 3.21
+
+ The version of intl found (x.y.z)
+
+.. variable:: Intl_VERSION_MAJOR
+
+ .. versionadded:: 3.21
+
+ The major version of intl
+
+.. variable:: Intl_VERSION_MINOR
+
+ .. versionadded:: 3.21
+
+ The minor version of intl
+
+.. variable:: Intl_VERSION_PATCH
+
+ .. versionadded:: 3.21
+
+ The patch version of intl
+
.. versionadded:: 3.20
This module defines :prop_tgt:`IMPORTED` target ``Intl::Intl``.
@@ -50,6 +74,10 @@ The following cache variables may also be set:
case.
.. note::
+ Some libintl implementations don't embed the version number in their header files.
+ In this case the variables ``Intl_VERSION*`` will be empty.
+
+.. note::
If you wish to use the Gettext tools (``msgmerge``,
``msgfmt``, etc.), use :module:`FindGettext`.
#]=======================================================================]
@@ -101,15 +129,39 @@ else()
DOC "libintl include directory")
mark_as_advanced(Intl_INCLUDE_DIR)
- find_library(Intl_LIBRARY "intl" "libintl" NAMES_PER_DIR
+ find_library(Intl_LIBRARY
+ NAMES "intl" "libintl"
+ NAMES_PER_DIR
DOC "libintl libraries (if not in the C library)")
mark_as_advanced(Intl_LIBRARY)
endif()
+# NOTE: glibc's libintl.h does not define LIBINTL_VERSION
+if(Intl_INCLUDE_DIR AND EXISTS "${Intl_INCLUDE_DIR}/libintl.h")
+ file(STRINGS ${Intl_INCLUDE_DIR}/libintl.h Intl_VERSION_DEFINE REGEX "LIBINTL_VERSION (.*)")
+
+ if(Intl_VERSION_DEFINE MATCHES "(0x[A-Fa-f0-9]+)")
+ set(Intl_VERSION_NUMBER "${CMAKE_MATCH_1}")
+ # encoding -> version number: (major<<16) + (minor<<8) + patch
+ math(EXPR Intl_VERSION_MAJOR "${Intl_VERSION_NUMBER} >> 16" OUTPUT_FORMAT HEXADECIMAL)
+ math(EXPR Intl_VERSION_MINOR "(${Intl_VERSION_NUMBER} - (${Intl_VERSION_MAJOR} << 16)) >> 8" OUTPUT_FORMAT HEXADECIMAL)
+ math(EXPR Intl_VERSION_PATCH "${Intl_VERSION_NUMBER} - ((${Intl_VERSION_MAJOR} << 16) + (${Intl_VERSION_MINOR} << 8))" OUTPUT_FORMAT HEXADECIMAL)
+
+ math(EXPR Intl_VERSION_MAJOR "${Intl_VERSION_MAJOR}" OUTPUT_FORMAT DECIMAL)
+ math(EXPR Intl_VERSION_MINOR "${Intl_VERSION_MINOR}" OUTPUT_FORMAT DECIMAL)
+ math(EXPR Intl_VERSION_PATCH "${Intl_VERSION_PATCH}" OUTPUT_FORMAT DECIMAL)
+ set(Intl_VERSION "${Intl_VERSION_MAJOR}.${Intl_VERSION_MINOR}.${Intl_VERSION_PATCH}")
+ endif()
+
+ unset(Intl_VERSION_DEFINE)
+ unset(Intl_VERSION_NUMBER)
+endif()
+
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Intl
FOUND_VAR Intl_FOUND
REQUIRED_VARS ${_Intl_REQUIRED_VARS}
+ VERSION_VAR Intl_VERSION
FAIL_MESSAGE "Failed to find Gettext libintl")
unset(_Intl_REQUIRED_VARS)
unset(_Intl_IS_BUILT_IN_MSG)
diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake
index 5aa2d601f..e4f60b316 100644
--- a/Modules/FindJNI.cmake
+++ b/Modules/FindJNI.cmake
@@ -80,7 +80,7 @@ macro(java_append_library_directories _var)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
set(_java_libarch "ppc" "ppc64")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^sparc")
- # Both flavours can run on the same processor
+ # Both flavors can run on the same processor
set(_java_libarch "${CMAKE_SYSTEM_PROCESSOR}" "sparc" "sparcv9")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(parisc|hppa)")
set(_java_libarch "parisc" "parisc64")
diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index 45e4be72f..3146e06d4 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -8,11 +8,11 @@ FindLAPACK
Find Linear Algebra PACKage (LAPACK) library
This module finds an installed Fortran library that implements the
-LAPACK linear-algebra interface (see http://www.netlib.org/lapack/).
+`LAPACK linear-algebra interface`_.
-The approach follows that taken for the ``autoconf`` macro file,
-``acx_lapack.m4`` (distributed at
-http://ac-archive.sourceforge.net/ac-archive/acx_lapack.html).
+At least one of the ``C``, ``CXX``, or ``Fortran`` languages must be enabled.
+
+.. _`LAPACK linear-algebra interface`: http://www.netlib.org/lapack/
Input Variables
^^^^^^^^^^^^^^^
@@ -23,51 +23,8 @@ The following variables may be set to influence this module's behavior:
if ``ON`` use static linkage
``BLA_VENDOR``
- If set, checks only the specified vendor, if not set checks all the
- possibilities. List of vendors valid in this module:
-
- * ``FlexiBLAS``
- * ``OpenBLAS``
- * ``FLAME``
- * ``Intel10_32`` (intel mkl v10 32 bit, threaded code)
- * ``Intel10_64lp`` (intel mkl v10+ 64 bit, threaded code, lp64 model)
- * ``Intel10_64lp_seq`` (intel mkl v10+ 64 bit, sequential code, lp64 model)
- * ``Intel10_64ilp`` (intel mkl v10+ 64 bit, threaded code, ilp64 model)
- * ``Intel10_64ilp_seq`` (intel mkl v10+ 64 bit, sequential code, ilp64 model)
- * ``Intel10_64_dyn`` (intel mkl v10+ 64 bit, single dynamic library)
- * ``Intel`` (obsolete versions of mkl 32 and 64 bit)
- * ``ACML``
- * ``Apple``
- * ``NAS``
- * ``Arm``
- * ``Arm_mp``
- * ``Arm_ilp64``
- * ``Arm_ilp64_mp``
- * ``EML``
- * ``EML_mt``
- * ``Generic``
-
- .. versionadded:: 3.6
- ``OpenBLAS`` support.
-
- .. versionadded:: 3.11
- ``FLAME`` support.
-
- .. versionadded:: 3.13
- Added ILP64 MKL variants (``Intel10_64ilp``, ``Intel10_64ilp_seq``).
-
- .. versionadded:: 3.17
- Added single dynamic library MKL variant (``Intel10_64_dyn``).
-
- .. versionadded:: 3.18
- Arm Performance Libraries support (``Arm``, ``Arm_mp``, ``Arm_ilp64``,
- ``Arm_ilp64_mp``).
-
- .. versionadded:: 3.19
- ``FlexiBLAS`` support.
-
- .. versionadded:: 3.20
- Elbrus Math Library support (``EML``, ``EML_mt``).
+ Set to one of the :ref:`BLAS/LAPACK Vendors` to search for BLAS only
+ from the specified vendor. If not set, all vendors are considered.
``BLA_F95``
if ``ON`` tries to find the BLAS95/LAPACK95 interfaces
@@ -81,11 +38,11 @@ The following variables may be set to influence this module's behavior:
Imported targets
^^^^^^^^^^^^^^^^
-.. versionadded:: 3.18
-
-This module defines the following :prop_tgt:`IMPORTED` target:
+This module defines the following :prop_tgt:`IMPORTED` targets:
``LAPACK::LAPACK``
+ .. versionadded:: 3.18
+
The libraries to use for LAPACK, if found.
Result Variables
@@ -106,52 +63,82 @@ This module defines the following variables:
``LAPACK95_FOUND``
library implementing the LAPACK95 interface is found
-.. note::
+Intel MKL
+^^^^^^^^^
+
+To use the Intel MKL implementation of LAPACK, a project must enable at least
+one of the ``C`` or ``CXX`` languages. Set ``BLA_VENDOR`` to an Intel MKL
+variant either on the command-line as ``-DBLA_VENDOR=Intel10_64lp`` or in
+project code:
- C, CXX or Fortran must be enabled to detect a BLAS/LAPACK library.
- C or CXX must be enabled to use Intel Math Kernel Library (MKL).
+.. code-block:: cmake
- For example, to use Intel MKL libraries and/or Intel compiler:
+ set(BLA_VENDOR Intel10_64lp)
+ find_package(LAPACK)
- .. code-block:: cmake
+In order to build a project using Intel MKL, and end user must first
+establish an Intel MKL environment. See the :module:`FindBLAS` module
+section on :ref:`Intel MKL` for details.
- set(BLA_VENDOR Intel10_64lp)
- find_package(LAPACK)
#]=======================================================================]
+# The approach follows that of the ``autoconf`` macro file, ``acx_lapack.m4``
+# (distributed at http://ac-archive.sourceforge.net/ac-archive/acx_lapack.html).
+
if(CMAKE_Fortran_COMPILER_LOADED)
include(${CMAKE_CURRENT_LIST_DIR}/CheckFortranFunctionExists.cmake)
else()
include(${CMAKE_CURRENT_LIST_DIR}/CheckFunctionExists.cmake)
endif()
-include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
function(_add_lapack_target)
if(LAPACK_FOUND AND NOT TARGET LAPACK::LAPACK)
add_library(LAPACK::LAPACK INTERFACE IMPORTED)
+
+ # Filter out redundant BLAS info and replace with the BLAS target
set(_lapack_libs "${LAPACK_LIBRARIES}")
- if(_lapack_libs AND TARGET BLAS::BLAS)
- # remove the ${BLAS_LIBRARIES} from the interface and replace it
- # with the BLAS::BLAS target
- list(REMOVE_ITEM _lapack_libs "${BLAS_LIBRARIES}")
+ set(_lapack_flags "${LAPACK_LINKER_FLAGS}")
+ if(TARGET BLAS::BLAS)
+ if(_lapack_libs AND BLAS_LIBRARIES)
+ foreach(_blas_lib IN LISTS BLAS_LIBRARIES)
+ list(REMOVE_ITEM _lapack_libs "${_blas_lib}")
+ endforeach()
+ endif()
+ if(_lapack_flags AND BLAS_LINKER_FLAGS)
+ foreach(_blas_flag IN LISTS BLAS_LINKER_FLAGS)
+ list(REMOVE_ITEM _lapack_flags "${_blas_flag}")
+ endforeach()
+ endif()
list(APPEND _lapack_libs BLAS::BLAS)
endif()
-
if(_lapack_libs)
set_target_properties(LAPACK::LAPACK PROPERTIES
INTERFACE_LINK_LIBRARIES "${_lapack_libs}"
)
endif()
- unset(_lapack_libs)
+ if(_lapack_flags)
+ set_target_properties(LAPACK::LAPACK PROPERTIES
+ INTERFACE_LINK_OPTIONS "${_lapack_flags}"
+ )
+ endif()
endif()
endfunction()
-macro(_lapack_find_library_setup)
- cmake_push_check_state()
- set(CMAKE_REQUIRED_QUIET ${LAPACK_FIND_QUIETLY})
+# TODO: move this stuff to a separate module
+
+function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs _blas)
+ # This function checks for the existence of the combination of libraries
+ # given by _list. If the combination is found, this checks whether can link
+ # against that library combination using the name of a routine given by _name
+ # using the linker flags given by _flags. If the combination of libraries is
+ # found and passes the link test, ${LIBRARIES} is set to the list of complete
+ # library paths that have been found. Otherwise, ${LIBRARIES} is set to FALSE.
+
+ set(_libraries_work TRUE)
+ set(_libraries)
+ set(_combined_name)
- set(_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
if(BLA_STATIC)
if(WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
@@ -164,33 +151,6 @@ macro(_lapack_find_library_setup)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf)
endif()
endif()
-endmacro()
-
-macro(_lapack_find_library_teardown)
- set(CMAKE_FIND_LIBRARY_SUFFIXES ${_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
- unset(_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES)
- cmake_pop_check_state()
-endmacro()
-
-# TODO: move this stuff to a separate module
-
-macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _addlibdir _subdirs _blas)
- # This macro checks for the existence of the combination of fortran libraries
- # given by _list. If the combination is found, this macro checks (using the
- # Check_Fortran_Function_Exists macro) whether can link against that library
- # combination using the name of a routine given by _name using the linker
- # flags given by _flags. If the combination of libraries is found and passes
- # the link test, LIBRARIES is set to the list of complete library paths that
- # have been found. Otherwise, LIBRARIES is set to FALSE.
-
- # N.B. _prefix is the prefix applied to the names of all cached variables that
- # are generated internally and marked advanced by this macro.
- # _addlibdir is a list of additional search paths. _subdirs is a list of path
- # suffixes to be used by find_library().
-
- set(_libraries_work TRUE)
- set(${LIBRARIES})
- set(_combined_name)
set(_extaddlibdir "${_addlibdir}")
if(WIN32)
@@ -203,31 +163,37 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a
list(APPEND _extaddlibdir "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}")
foreach(_library ${_list})
- if(_library MATCHES "^-Wl,--(start|end)-group$")
- # Respect linker flags like --start/end-group (required by MKL)
- set(${LIBRARIES} ${${LIBRARIES}} "${_library}")
+ if(_library MATCHES "^-")
+ # Respect linker flags as-is (required by MKL)
+ list(APPEND _libraries "${_library}")
else()
- set(_combined_name ${_combined_name}_${_library})
+ string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}")
+ set(_combined_name ${_combined_name}_${_lib_var})
+ if(NOT "${_deps}" STREQUAL "")
+ set(_combined_name ${_combined_name}_deps)
+ endif()
if(_libraries_work)
- find_library(${_prefix}_${_library}_LIBRARY
+ find_library(${_prefix}_${_lib_var}_LIBRARY
NAMES ${_library}
NAMES_PER_DIR
PATHS ${_extaddlibdir}
PATH_SUFFIXES ${_subdirs}
)
- #message("DEBUG: find_library(${_library}) got ${${_prefix}_${_library}_LIBRARY}")
- mark_as_advanced(${_prefix}_${_library}_LIBRARY)
- set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
- set(_libraries_work ${${_prefix}_${_library}_LIBRARY})
+ mark_as_advanced(${_prefix}_${_lib_var}_LIBRARY)
+ list(APPEND _libraries ${${_prefix}_${_lib_var}_LIBRARY})
+ set(_libraries_work ${${_prefix}_${_lib_var}_LIBRARY})
endif()
endif()
endforeach()
- unset(_library)
+ foreach(_flag ${_flags})
+ string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}")
+ set(_combined_name ${_combined_name}_${_flag_var})
+ endforeach()
if(_libraries_work)
# Test this combination of libraries.
- set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_blas} ${_threadlibs})
- #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}")
+ set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${_libraries} ${_blas} ${_deps})
+ set(CMAKE_REQUIRED_QUIET ${LAPACK_FIND_QUIETLY})
if(CMAKE_Fortran_COMPILER_LOADED)
check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS)
else()
@@ -239,19 +205,15 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a
if(_libraries_work)
if("${_list}${_blas}" STREQUAL "")
- set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
+ set(_libraries "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
else()
- set(${LIBRARIES} ${${LIBRARIES}} ${_blas} ${_threadlibs})
+ list(APPEND _libraries ${_blas} ${_deps})
endif()
else()
- set(${LIBRARIES} FALSE)
+ set(_libraries FALSE)
endif()
-
- unset(_extaddlibdir)
- unset(_libraries_work)
- unset(_combined_name)
- #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}")
-endmacro()
+ set(${LIBRARIES} "${_libraries}" PARENT_SCOPE)
+endfunction()
macro(_lapack_find_dependency dep)
set(_lapack_quiet_arg)
@@ -274,11 +236,10 @@ macro(_lapack_find_dependency dep)
set(_lapack_quiet_arg)
endmacro()
-_lapack_find_library_setup()
-
set(LAPACK_LINKER_FLAGS)
set(LAPACK_LIBRARIES)
set(LAPACK95_LIBRARIES)
+set(_lapack_fphsa_req_var LAPACK_LIBRARIES)
# Check the language being used
if(NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED))
@@ -385,7 +346,9 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
"compiler/lib/${LAPACK_mkl_ARCH_NAME}"
"mkl/lib" "mkl/lib/${LAPACK_mkl_ARCH_NAME}_${LAPACK_mkl_OS_NAME}"
"mkl/lib/${LAPACK_mkl_ARCH_NAME}"
- "lib/${LAPACK_mkl_ARCH_NAME}_${LAPACK_mkl_OS_NAME}")
+ "lib" "lib/${LAPACK_mkl_ARCH_NAME}_${LAPACK_mkl_OS_NAME}"
+ "lib/${LAPACK_mkl_ARCH_NAME}"
+ )
# First try empty lapack libs
if(NOT ${_LIBRARIES})
@@ -585,22 +548,78 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
)
endif()
+ # Fujitsu SSL2 Library?
+ if(NOT LAPACK_LIBRARIES
+ AND (BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All"))
+ if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP")
+ set(_ssl2_suffix BLAMP)
+ else()
+ set(_ssl2_suffix)
+ endif()
+ set(_ssl2_blas)
+ if(BLAS_LIBRARIES STREQUAL "")
+ set(_ssl2_blas "${BLAS_LINKER_FLAGS}")
+ else()
+ set(_ssl2_blas "${BLAS_LIBRARIES} ${BLAS_LINKER_FLAGS}")
+ endif()
+ check_lapack_libraries(
+ LAPACK_LIBRARIES
+ LAPACK
+ cheev
+ "-SSL2${_ssl2_suffix}"
+ ""
+ ""
+ ""
+ ""
+ "${_ssl2_blas}"
+ )
+ if(LAPACK_LIBRARIES)
+ set(LAPACK_LINKER_FLAGS "-SSL2${_ssl2_suffix}")
+ set(_lapack_fphsa_req_var LAPACK_LINKER_FLAGS)
+ endif()
+ unset(_ssl2_suffix)
+ endif()
+
+ # NVHPC Library?
+ if(NOT LAPACK_LIBRARIES
+ AND (BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All"))
+ check_lapack_libraries(
+ LAPACK_LIBRARIES
+ LAPACK
+ cheev
+ ""
+ "lapack"
+ "-fortranlibs"
+ ""
+ ""
+ "${BLAS_LIBRARIES}"
+ )
+ endif()
+
# Generic LAPACK library?
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR STREQUAL "Generic"
OR BLA_VENDOR STREQUAL "ATLAS"
OR BLA_VENDOR STREQUAL "All"))
+ if(BLA_STATIC)
+ # We do not know for sure how the LAPACK reference implementation
+ # is built on this host. Guess typical dependencies.
+ set(_lapack_generic_deps "-lgfortran;-lm")
+ else()
+ set(_lapack_generic_deps "")
+ endif()
check_lapack_libraries(
LAPACK_LIBRARIES
LAPACK
cheev
""
"lapack"
- ""
+ "${_lapack_generic_deps}"
""
""
"${BLAS_LIBRARIES}"
)
+ unset(_lapack_generic_deps)
endif()
endif()
@@ -612,7 +631,7 @@ if(LAPACK_NOT_FOUND_MESSAGE)
set(LAPACK_NOT_FOUND_MESSAGE
REASON_FAILURE_MESSAGE ${LAPACK_NOT_FOUND_MESSAGE})
endif()
-find_package_handle_standard_args(LAPACK REQUIRED_VARS LAPACK_LIBRARIES
+find_package_handle_standard_args(LAPACK REQUIRED_VARS ${_lapack_fphsa_req_var}
${LAPACK_NOT_FOUND_MESSAGE})
unset(LAPACK_NOT_FOUND_MESSAGE)
@@ -627,5 +646,3 @@ if(LAPACK_LIBRARIES STREQUAL "LAPACK_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
endif()
_add_lapack_target()
-
-_lapack_find_library_teardown()
diff --git a/Modules/FindLATEX.cmake b/Modules/FindLATEX.cmake
index 1e82651fe..9d7168ee8 100644
--- a/Modules/FindLATEX.cmake
+++ b/Modules/FindLATEX.cmake
@@ -61,6 +61,10 @@ if (WIN32)
# Try to find the MikTex binary path (look for its package manager).
find_path(MIKTEX_BINARY_PATH mpm.exe
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MiK\\MiKTeX\\CurrentVersion\\MiKTeX;Install Root]/miktex/bin"
+ "$ENV{LOCALAPPDATA}/Programs/MiKTeX/miktex/bin"
+ "$ENV{LOCALAPPDATA}/Programs/MiKTeX/miktex/bin/x64"
+ "$ENV{APPDATA}/Programs/MiKTeX/miktex/bin"
+ "$ENV{APPDATA}/Programs/MiKTeX/miktex/bin/x64"
DOC
"Path to the MikTex binary directory."
)
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index de38ac20c..c48decbb9 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -277,6 +277,11 @@ set(_MPI_Fortran_GENERIC_COMPILER_NAMES mpif95 mpif95_r mpf95 mpf95_r
mpif77 mpif77_r mpf77 mpf77_r
mpifc)
+#Fujitsu cross/own compiler names
+set(_MPI_Fujitsu_C_COMPILER_NAMES mpifccpx mpifcc)
+set(_MPI_Fujitsu_CXX_COMPILER_NAMES mpiFCCpx mpiFCC)
+set(_MPI_Fujitsu_Fortran_COMPILER_NAMES mpifrtpx mpifrt)
+
# GNU compiler names
set(_MPI_GNU_C_COMPILER_NAMES mpigcc mpgcc mpigcc_r mpgcc_r)
set(_MPI_GNU_CXX_COMPILER_NAMES mpig++ mpg++ mpig++_r mpg++_r mpigxx)
@@ -337,7 +342,7 @@ set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95
# pick up the right settings for it.
foreach (LANG IN ITEMS C CXX Fortran)
set(_MPI_${LANG}_COMPILER_NAMES "")
- foreach (id IN ITEMS GNU Intel IntelLLVM MSVC PGI XL)
+ foreach (id IN ITEMS Fujitsu FujitsuClang GNU Intel IntelLLVM MSVC PGI XL)
if (NOT CMAKE_${LANG}_COMPILER_ID OR CMAKE_${LANG}_COMPILER_ID STREQUAL id)
foreach(_COMPILER_NAME IN LISTS _MPI_${id}_${LANG}_COMPILER_NAMES)
list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_COMPILER_NAME}${MPI_EXECUTABLE_SUFFIX})
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index 2f56d1571..c8df670b1 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -52,7 +52,7 @@ The module supports the following components:
between the release name and the version.
The variable :variable:`Matlab_ROOT_DIR` may be specified in order to give
-the path of the desired Matlab version. Otherwise, the behaviour is platform
+the path of the desired Matlab version. Otherwise, the behavior is platform
specific:
* Windows: The installed versions of Matlab/MCR are retrieved from the
@@ -83,7 +83,7 @@ Module Input Variables
^^^^^^^^^^^^^^^^^^^^^^
Users or projects may set the following variables to configure the module
-behaviour:
+behavior:
:variable:`Matlab_ROOT_DIR`
the root of the Matlab installation.
@@ -184,7 +184,7 @@ Known issues
**Symbol clash in a MEX target**
By default, every symbols inside a MEX
file defined with the command :command:`matlab_add_mex` have hidden
- visibility, except for the entry point. This is the default behaviour of
+ visibility, except for the entry point. This is the default behavior of
the MEX compiler, which lowers the risk of symbol collision between the
libraries shipped with Matlab, and the libraries to which the MEX file is
linking to. This is also the default on Windows platforms.
@@ -223,7 +223,7 @@ Reference
.. variable:: MATLAB_ADDITIONAL_VERSIONS
If set, specifies additional versions of Matlab that may be looked for.
- The variable should be a list of strings, organised by pairs of release
+ The variable should be a list of strings, organized by pairs of release
name and versions, such as follows::
set(MATLAB_ADDITIONAL_VERSIONS
@@ -856,7 +856,7 @@ endfunction()
where ``matlab_file_name`` is the ``UNITTEST_FILE`` without the extension.
``UNITTEST_PRECOMMAND``
Matlab script command to be ran before the file
- containing the test (eg. GPU device initialisation based on CMake
+ containing the test (eg. GPU device initialization based on CMake
variables).
``TIMEOUT``
the test timeout in seconds. Defaults to 180 seconds as the
@@ -1240,7 +1240,7 @@ function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_ve
endif()
endif()
- # UNKNOWN is the default behaviour in case we
+ # UNKNOWN is the default behavior in case we
# - have an erroneous matlab_root
# - have an initial 'UNKNOWN'
if(matlab_or_mcr STREQUAL "MATLAB" OR matlab_or_mcr STREQUAL "UNKNOWN")
@@ -1375,7 +1375,7 @@ function(_Matlab_find_instances_osx matlab_roots)
set(_matlab_possible_roots)
# on mac, we look for the /Application paths
- # this corresponds to the behaviour on Windows. On Linux, we do not have
+ # this corresponds to the behavior on Windows. On Linux, we do not have
# any other guess.
matlab_get_supported_releases(_matlab_releases)
if(MATLAB_FIND_DEBUG)
@@ -1416,7 +1416,7 @@ function(_Matlab_find_instances_from_path matlab_roots)
set(_matlab_possible_roots)
# At this point, we have no other choice than trying to find it from PATH.
- # If set by the user, this wont change
+ # If set by the user, this won't change.
find_program(
_matlab_main_tmp
NAMES matlab)
@@ -1552,7 +1552,7 @@ if(_numbers_of_matlab_roots GREATER 0)
# adding a warning in case of ambiguity
if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG)
message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})."
- " If this is not the desired behaviour, use the EXACT keyword or provide the -DMatlab_ROOT_DIR=... on the command line")
+ " If this is not the desired behavior, use the EXACT keyword or provide the -DMatlab_ROOT_DIR=... on the command line")
endif()
endif()
endif()
diff --git a/Modules/FindMsys.cmake b/Modules/FindMsys.cmake
new file mode 100644
index 000000000..b4796d295
--- /dev/null
+++ b/Modules/FindMsys.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.
+
+#[=======================================================================[.rst:
+FindMsys
+--------
+
+.. versionadded:: 3.21
+
+Find MSYS, a POSIX-compatible environment that runs natively
+on Microsoft Windows
+#]=======================================================================]
+
+if (WIN32)
+ if(MSYS_INSTALL_PATH)
+ set(MSYS_CMD "${MSYS_INSTALL_PATH}/msys2_shell.cmd")
+ endif()
+
+ find_program(MSYS_CMD
+ NAMES msys2_shell.cmd
+ PATHS
+ "C:/msys64"
+ "C:/msys32"
+ "C:/MSYS"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MSYS\\setup;rootdir]"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Cygnus Solutions\\MSYS\\mounts v2\\/;native]"
+ )
+ get_filename_component(MSYS_INSTALL_PATH "${MSYS_CMD}" DIRECTORY)
+ mark_as_advanced(MSYS_CMD)
+
+endif ()
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index 52330a497..929a80988 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -130,6 +130,8 @@ function(_OPENMP_FLAG_CANDIDATES LANG)
set(OMP_FLAG_XL "-qsmp=omp")
# Cray compiler activate OpenMP with -h omp, which is enabled by default.
set(OMP_FLAG_Cray " " "-h omp")
+ set(OMP_FLAG_Fujitsu "-Kopenmp" "-KOMP")
+ set(OMP_FLAG_FujitsuClang "-fopenmp" "-Kopenmp")
# If we know the correct flags, use those
if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID})
@@ -568,6 +570,10 @@ 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")
+ set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
+ INTERFACE_LINK_OPTIONS "${OpenMP_${LANG}_FLAGS}")
+ endif()
unset(_OpenMP_${LANG}_OPTIONS)
endif()
if(OpenMP_${LANG}_INCLUDE_DIRS)
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index b1afa5f40..8474e05c5 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -123,6 +123,10 @@ function(_OpenSSL_target_add_dependencies target)
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads )
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS} )
endif()
+ if(WIN32 AND OPENSSL_USE_STATIC_LIBS)
+ set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ws2_32 )
+ set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES crypt32 )
+ endif()
endfunction()
if (UNIX)
diff --git a/Modules/FindPerl.cmake b/Modules/FindPerl.cmake
index c14e059e9..26962dff7 100644
--- a/Modules/FindPerl.cmake
+++ b/Modules/FindPerl.cmake
@@ -17,9 +17,11 @@ this module looks for Perl
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake)
set(PERL_POSSIBLE_BIN_PATHS
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
if(WIN32)
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index 38c8da754..3bc9dba16 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -265,9 +265,7 @@ endfunction()
# create an imported target from all the information returned by pkg-config
function(_pkg_create_imp_target _prefix _imp_target_global)
- # only create the target if it is linkable, i.e. no executables
- if (NOT TARGET PkgConfig::${_prefix}
- AND ( ${_prefix}_INCLUDE_DIRS OR ${_prefix}_LINK_LIBRARIES OR ${_prefix}_LDFLAGS_OTHER OR ${_prefix}_CFLAGS_OTHER ))
+ if (NOT TARGET PkgConfig::${_prefix})
if(${_imp_target_global})
set(_global_opt "GLOBAL")
else()
diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake
index 4b1e33689..c73a2d81a 100644
--- a/Modules/FindProtobuf.cmake
+++ b/Modules/FindProtobuf.cmake
@@ -140,7 +140,7 @@ Example:
function(protobuf_generate)
set(_options APPEND_PATH DESCRIPTORS)
- set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR)
+ set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN)
if(COMMAND target_sources)
list(APPEND _singleargs TARGET)
endif()
@@ -171,6 +171,10 @@ function(protobuf_generate)
set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}:")
endif()
+ if(protobuf_generate_PLUGIN)
+ set(_plugin "--plugin=${protobuf_generate_PLUGIN}")
+ endif()
+
if(NOT protobuf_generate_GENERATE_EXTENSIONS)
if(protobuf_generate_LANGUAGE STREQUAL cpp)
set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc)
@@ -245,7 +249,7 @@ function(protobuf_generate)
add_custom_command(
OUTPUT ${_generated_srcs}
COMMAND protobuf::protoc
- ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_dll_desc_out} ${_protobuf_include_path} ${_abs_file}
+ ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_dll_desc_out} ${_protobuf_include_path} ${_abs_file}
DEPENDS ${_abs_file} protobuf::protoc
COMMENT "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}"
VERBATIM )
diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake
index ee07f8345..759f57c22 100644
--- a/Modules/FindRuby.cmake
+++ b/Modules/FindRuby.cmake
@@ -435,7 +435,7 @@ endif()
# Determine the list of possible names for the ruby library
-set(_Ruby_POSSIBLE_LIB_NAMES ruby ruby-static ruby${_Ruby_VERSION_SHORT} ruby${_Ruby_VERSION_SHORT_NODOT} ruby-${_Ruby_VERSION_SHORT} ruby-${Ruby_VERSION})
+set(_Ruby_POSSIBLE_LIB_NAMES ruby ruby-static ruby${_Ruby_VERSION_SHORT} ruby${_Ruby_VERSION_SHORT_NODOT} ruby${_Ruby_NODOT_VERSION} ruby-${_Ruby_VERSION_SHORT} ruby-${Ruby_VERSION})
if(WIN32)
set(_Ruby_POSSIBLE_MSVC_RUNTIMES "msvcrt;vcruntime140;vcruntime140_1")
diff --git a/Modules/FindSWIG.cmake b/Modules/FindSWIG.cmake
index 4c7ad89dc..7c610d978 100644
--- a/Modules/FindSWIG.cmake
+++ b/Modules/FindSWIG.cmake
@@ -87,56 +87,68 @@ if (NOT _SWIG_NAMES)
endif()
find_program(SWIG_EXECUTABLE NAMES ${_SWIG_NAMES} swig)
+unset(_SWIG_NAMES)
-if(SWIG_EXECUTABLE)
- execute_process(COMMAND ${SWIG_EXECUTABLE} -swiglib
- OUTPUT_VARIABLE SWIG_swiglib_output
- ERROR_VARIABLE SWIG_swiglib_error
- RESULT_VARIABLE SWIG_swiglib_result)
+if(SWIG_EXECUTABLE AND NOT SWIG_DIR)
+ # Find default value for SWIG library directory
+ execute_process(COMMAND "${SWIG_EXECUTABLE}" -swiglib
+ OUTPUT_VARIABLE _swig_output
+ ERROR_VARIABLE _swig_error
+ RESULT_VARIABLE _swig_result)
- if(SWIG_swiglib_result)
+ if(_swig_result)
+ set(_msg "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${_swig_error}")
if(SWIG_FIND_REQUIRED)
- message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${SWIG_swiglib_error}")
+ message(SEND_ERROR "${_msg}")
else()
- message(STATUS "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${SWIG_swiglib_error}")
+ message(STATUS "${_msg}")
endif()
+ unset(_msg)
else()
- string(REGEX REPLACE "[\n\r]+" ";" SWIG_swiglib_output ${SWIG_swiglib_output})
- find_path(SWIG_DIR swig.swg PATHS ${SWIG_swiglib_output} NO_CMAKE_FIND_ROOT_PATH)
- if(SWIG_DIR)
- set(SWIG_USE_FILE ${CMAKE_CURRENT_LIST_DIR}/UseSWIG.cmake)
- execute_process(COMMAND ${SWIG_EXECUTABLE} -version
- OUTPUT_VARIABLE SWIG_version_output
- ERROR_VARIABLE SWIG_version_output
- RESULT_VARIABLE SWIG_version_result)
- if(SWIG_version_result)
- message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -version\" failed with output:\n${SWIG_version_output}")
- else()
- string(REGEX REPLACE ".*SWIG Version[^0-9.]*\([0-9.]+\).*" "\\1"
- SWIG_version_output "${SWIG_version_output}")
- set(SWIG_VERSION ${SWIG_version_output} CACHE STRING "Swig version" FORCE)
- endif()
- endif()
+ string(REGEX REPLACE "[\n\r]+" ";" _SWIG_LIB ${_swig_output})
endif()
- if(SWIG_FIND_COMPONENTS)
- execute_process(COMMAND ${SWIG_EXECUTABLE} -help
- OUTPUT_VARIABLE SWIG_swighelp_output
- ERROR_VARIABLE SWIG_swighelp_error
- RESULT_VARIABLE SWIG_swighelp_result)
- if(SWIG_swighelp_result)
- message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -help\" failed with output:\n${SWIG_swiglib_error}")
- else()
- string(REPLACE "\n" ";" SWIG_swighelp_output "${SWIG_swighelp_output}")
- foreach(SWIG_line IN LISTS SWIG_swighelp_output)
- if(SWIG_line MATCHES "-([A-Za-z0-9_]+) +- *Generate.*wrappers")
- set(SWIG_${CMAKE_MATCH_1}_FOUND TRUE)
- endif()
- endforeach()
- endif()
+ # Find SWIG library directory
+ find_path(SWIG_DIR swig.swg PATHS ${_SWIG_LIB} NO_CMAKE_FIND_ROOT_PATH)
+ unset(_SWIG_LIB)
+endif()
+
+if(SWIG_EXECUTABLE AND SWIG_DIR AND NOT SWIG_VERSION)
+ # Determine SWIG version
+ execute_process(COMMAND "${SWIG_EXECUTABLE}" -version
+ OUTPUT_VARIABLE _swig_output
+ ERROR_VARIABLE _swig_output
+ RESULT_VARIABLE _swig_result)
+ if(_swig_result)
+ message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -version\" failed with output:\n${_swig_output}")
+ else()
+ string(REGEX REPLACE ".*SWIG Version[^0-9.]*\([0-9.]+\).*" "\\1"
+ _swig_output "${_swig_output}")
+ set(SWIG_VERSION ${_swig_output} CACHE STRING "Swig version" FORCE)
+ endif()
+endif()
+
+if(SWIG_EXECUTABLE AND SWIG_FIND_COMPONENTS)
+ execute_process(COMMAND "${SWIG_EXECUTABLE}" -help
+ OUTPUT_VARIABLE _swig_output
+ ERROR_VARIABLE _swig_error
+ RESULT_VARIABLE _swig_result)
+ if(_swig_result)
+ message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -help\" failed with output:\n${_swig_error}")
+ else()
+ string(REPLACE "\n" ";" _swig_output "${_swig_output}")
+ foreach(SWIG_line IN LISTS _swig_output)
+ if(SWIG_line MATCHES "-([A-Za-z0-9_]+) +- *Generate.*wrappers")
+ set(SWIG_${CMAKE_MATCH_1}_FOUND TRUE)
+ endif()
+ endforeach()
endif()
endif()
+unset(_swig_output)
+unset(_swig_error)
+unset(_swig_result)
+
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(
SWIG HANDLE_COMPONENTS
@@ -144,4 +156,8 @@ find_package_handle_standard_args(
VERSION_VAR SWIG_VERSION
HANDLE_VERSION_RANGE)
+if(SWIG_FOUND)
+ set(SWIG_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/UseSWIG.cmake")
+endif()
+
mark_as_advanced(SWIG_DIR SWIG_VERSION SWIG_EXECUTABLE)
diff --git a/Modules/FindSelfPackers.cmake b/Modules/FindSelfPackers.cmake
index 1abbcbd7a..a6eb6e5f0 100644
--- a/Modules/FindSelfPackers.cmake
+++ b/Modules/FindSelfPackers.cmake
@@ -17,15 +17,18 @@ executables or shared libs. Examples:
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake)
find_program(SELF_PACKER_FOR_EXECUTABLE
upx
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
find_program(SELF_PACKER_FOR_SHARED_LIB
upx
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
mark_as_advanced(
diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake
index 87e88bc31..c6a3451f7 100644
--- a/Modules/FindThreads.cmake
+++ b/Modules/FindThreads.cmake
@@ -119,7 +119,10 @@ macro(_check_pthreads_flag)
${CMAKE_BINARY_DIR}
${_threads_src}
CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread
- OUTPUT_VARIABLE OUTPUT)
+ OUTPUT_VARIABLE _cmake_check_pthreads_output)
+
+ string(APPEND _cmake_find_threads_output "${_cmake_check_pthreads_output}")
+ unset(_cmake_check_pthreads_output)
unset(_threads_src)
if(THREADS_HAVE_PTHREAD_ARG)
@@ -127,9 +130,6 @@ macro(_check_pthreads_flag)
message(CHECK_PASS "yes")
else()
message(CHECK_FAIL "no")
- file(APPEND
- ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Determining if compiler accepts -pthread failed with the following output:\n${OUTPUT}\n\n")
endif()
endif()
@@ -225,7 +225,7 @@ if(CMAKE_USE_PTHREADS_INIT)
set(CMAKE_THREAD_LIBS_INIT )
endif()
- if(CMAKE_SYSTEM MATCHES "CYGWIN_NT")
+ if(CMAKE_SYSTEM MATCHES "CYGWIN_NT" OR CMAKE_SYSTEM MATCHES "MSYS_NT")
set(CMAKE_USE_PTHREADS_INIT 1)
set(Threads_FOUND TRUE)
set(CMAKE_THREAD_LIBS_INIT )
@@ -249,4 +249,10 @@ if(THREADS_FOUND AND NOT TARGET Threads::Threads)
if(CMAKE_THREAD_LIBS_INIT)
set_property(TARGET Threads::Threads PROPERTY INTERFACE_LINK_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
endif()
+elseif(NOT THREADS_FOUND AND _cmake_find_threads_output)
+ file(APPEND
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if compiler accepts -pthread failed with the following output:\n${_cmake_find_threads_output}\n\n")
endif()
+
+unset(_cmake_find_threads_output)
diff --git a/Modules/FindUnixCommands.cmake b/Modules/FindUnixCommands.cmake
index 2513f5c29..97739fa14 100644
--- a/Modules/FindUnixCommands.cmake
+++ b/Modules/FindUnixCommands.cmake
@@ -13,10 +13,12 @@ This module looks for the Unix commands ``bash``, ``cp``, ``gzip``,
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake)
find_program(BASH
bash
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
mark_as_advanced(
BASH
@@ -25,6 +27,7 @@ mark_as_advanced(
find_program(CP
cp
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
mark_as_advanced(
CP
@@ -33,6 +36,7 @@ mark_as_advanced(
find_program(GZIP
gzip
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
mark_as_advanced(
GZIP
@@ -41,6 +45,7 @@ mark_as_advanced(
find_program(MV
mv
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
mark_as_advanced(
MV
@@ -49,6 +54,7 @@ mark_as_advanced(
find_program(RM
rm
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
mark_as_advanced(
RM
@@ -60,6 +66,7 @@ find_program(TAR
gtar
PATH
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
mark_as_advanced(
TAR
diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake
index ceb1921e9..4f48e135a 100644
--- a/Modules/FindVulkan.cmake
+++ b/Modules/FindVulkan.cmake
@@ -13,12 +13,28 @@ and computing API.
IMPORTED Targets
^^^^^^^^^^^^^^^^
-This module defines :prop_tgt:`IMPORTED` target ``Vulkan::Vulkan``, if
-Vulkan has been found.
+This module defines :prop_tgt:`IMPORTED` targets if Vulkan has been found:
-.. versionadded:: 3.19
- This module defines :prop_tgt:`IMPORTED` target ``Vulkan::glslc``, if
- Vulkan and the GLSLC SPIR-V compiler has been found.
+``Vulkan::Vulkan``
+ The main Vulkan library.
+
+``Vulkan::glslc``
+ .. versionadded:: 3.19
+
+ The GLSLC SPIR-V compiler, if it has been found.
+
+``Vulkan::Headers``
+ .. versionadded:: 3.21
+
+ Provides just Vulkan headers include paths, if found. No library is
+ included in this target. This can be useful for applications that
+ load Vulkan library dynamically.
+
+``Vulkan::glslangValidator``
+ .. versionadded:: 3.21
+
+ The glslangValidator tool, if found. It is used to compile GLSL and
+ HLSL shaders into SPIR-V.
Result Variables
^^^^^^^^^^^^^^^^
@@ -34,6 +50,7 @@ The module will also define three cache variables::
Vulkan_INCLUDE_DIR - the Vulkan include directory
Vulkan_LIBRARY - the path to the Vulkan library
Vulkan_GLSLC_EXECUTABLE - the path to the GLSL SPIR-V compiler
+ Vulkan_GLSLANG_VALIDATOR_EXECUTABLE - the path to the glslangValidator tool
Hints
^^^^^
@@ -67,6 +84,11 @@ if(WIN32)
HINTS
"$ENV{VULKAN_SDK}/Bin"
)
+ find_program(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE
+ NAMES glslangValidator
+ HINTS
+ "$ENV{VULKAN_SDK}/Bin"
+ )
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
find_library(Vulkan_LIBRARY
NAMES vulkan-1
@@ -79,6 +101,11 @@ if(WIN32)
HINTS
"$ENV{VULKAN_SDK}/Bin32"
)
+ find_program(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE
+ NAMES glslangValidator
+ HINTS
+ "$ENV{VULKAN_SDK}/Bin32"
+ )
endif()
else()
find_path(Vulkan_INCLUDE_DIR
@@ -90,6 +117,9 @@ else()
find_program(Vulkan_GLSLC_EXECUTABLE
NAMES glslc
HINTS "$ENV{VULKAN_SDK}/bin")
+ find_program(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE
+ NAMES glslangValidator
+ HINTS "$ENV{VULKAN_SDK}/bin")
endif()
set(Vulkan_LIBRARIES ${Vulkan_LIBRARY})
@@ -100,7 +130,8 @@ find_package_handle_standard_args(Vulkan
DEFAULT_MSG
Vulkan_LIBRARY Vulkan_INCLUDE_DIR)
-mark_as_advanced(Vulkan_INCLUDE_DIR Vulkan_LIBRARY Vulkan_GLSLC_EXECUTABLE)
+mark_as_advanced(Vulkan_INCLUDE_DIR Vulkan_LIBRARY Vulkan_GLSLC_EXECUTABLE
+ Vulkan_GLSLANG_VALIDATOR_EXECUTABLE)
if(Vulkan_FOUND AND NOT TARGET Vulkan::Vulkan)
add_library(Vulkan::Vulkan UNKNOWN IMPORTED)
@@ -109,7 +140,18 @@ if(Vulkan_FOUND AND NOT TARGET Vulkan::Vulkan)
INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}")
endif()
+if(Vulkan_FOUND AND NOT TARGET Vulkan::Headers)
+ add_library(Vulkan::Headers INTERFACE IMPORTED)
+ set_target_properties(Vulkan::Headers PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}")
+endif()
+
if(Vulkan_FOUND AND Vulkan_GLSLC_EXECUTABLE AND NOT TARGET Vulkan::glslc)
add_executable(Vulkan::glslc IMPORTED)
set_property(TARGET Vulkan::glslc PROPERTY IMPORTED_LOCATION "${Vulkan_GLSLC_EXECUTABLE}")
endif()
+
+if(Vulkan_FOUND AND Vulkan_GLSLANG_VALIDATOR_EXECUTABLE AND NOT TARGET Vulkan::glslangValidator)
+ add_executable(Vulkan::glslangValidator IMPORTED)
+ set_property(TARGET Vulkan::glslangValidator PROPERTY IMPORTED_LOCATION "${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE}")
+endif()
diff --git a/Modules/FindWget.cmake b/Modules/FindWget.cmake
index bd01ec201..d0b6fdf44 100644
--- a/Modules/FindWget.cmake
+++ b/Modules/FindWget.cmake
@@ -16,10 +16,12 @@ This module looks for wget. This module defines the following values:
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake)
find_program(WGET_EXECUTABLE
wget
${CYGWIN_INSTALL_PATH}/bin
+ ${MSYS_INSTALL_PATH}/usr/bin
)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake
index 998faf1ec..9e5726b03 100644
--- a/Modules/FortranCInterface/Detect.cmake
+++ b/Modules/FortranCInterface/Detect.cmake
@@ -6,14 +6,17 @@ configure_file(${FortranCInterface_SOURCE_DIR}/Input.cmake.in
# Detect the Fortran/C interface on the first run or when the
# configuration changes.
-if(${FortranCInterface_BINARY_DIR}/Input.cmake
- IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
- OR ${FortranCInterface_SOURCE_DIR}/Output.cmake.in
- IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
- OR ${FortranCInterface_SOURCE_DIR}/CMakeLists.txt
- IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
- OR ${CMAKE_CURRENT_LIST_FILE}
- IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
+if(NOT EXISTS ${FortranCInterface_BINARY_DIR}/Output.cmake
+ OR NOT EXISTS ${FortranCInterface_BINARY_DIR}/Input.cmake
+ OR NOT EXISTS ${FortranCInterface_BINARY_DIR}/Output.cmake.in
+ OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake
+ IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Input.cmake
+ OR NOT ${FortranCInterface_SOURCE_DIR}/Output.cmake
+ IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake.in
+ OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake
+ IS_NEWER_THAN ${FortranCInterface_SOURCE_DIR}/CMakeLists.txt
+ OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake
+ IS_NEWER_THAN ${CMAKE_CURRENT_LIST_FILE}
)
message(CHECK_START "Detecting Fortran/C Interface")
else()
diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake
index 4016a6488..d81033ca9 100644
--- a/Modules/GNUInstallDirs.cmake
+++ b/Modules/GNUInstallDirs.cmake
@@ -239,6 +239,7 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set
endif()
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$"
AND NOT CMAKE_CROSSCOMPILING
+ AND NOT EXISTS "/etc/alpine-release"
AND NOT EXISTS "/etc/arch-release")
if (EXISTS "/etc/debian_version") # is this a debian system ?
if(CMAKE_LIBRARY_ARCHITECTURE)
@@ -349,10 +350,10 @@ mark_as_advanced(
macro(GNUInstallDirs_get_absolute_install_dir absvar var)
set(GGAID_extra_args ${ARGN})
list(LENGTH GGAID_extra_args GGAID_extra_arg_count)
- if(GGAID_extra_arg_count GREATER "0")
+ if(GGAID_extra_arg_count GREATER 0)
list(GET GGAID_extra_args 0 GGAID_dir)
else()
- # Historical behaviour: use ${dir} from caller's scope
+ # Historical behavior: use ${dir} from caller's scope
set(GGAID_dir "${dir}")
message(AUTHOR_WARNING
"GNUInstallDirs_get_absolute_install_dir called without third argument. "
diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake
index ed5c38b05..e90a9b5b7 100644
--- a/Modules/GetPrerequisites.cmake
+++ b/Modules/GetPrerequisites.cmake
@@ -83,7 +83,7 @@ to 1 all prerequisites will be found recursively, if set to 0 only
direct prerequisites are listed. <exclude_system> must be 0 or 1
indicating whether to include or exclude "system" prerequisites. With
<verbose> set to 0 only the full path names of the prerequisites are
-printed, set to 1 extra informatin will be displayed.
+printed, set to 1 extra information will be displayed.
::
diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake
index 2ea9e7425..80d8e2397 100644
--- a/Modules/GoogleTest.cmake
+++ b/Modules/GoogleTest.cmake
@@ -504,7 +504,8 @@ function(gtest_discover_tests TARGET)
string(CONCAT ctest_include_content
"if(EXISTS \"$<TARGET_FILE:${TARGET}>\")" "\n"
- " if(\"$<TARGET_FILE:${TARGET}>\" IS_NEWER_THAN \"${ctest_tests_file}\")" "\n"
+ " if(NOT EXISTS \"${ctest_tests_file}\" OR" "\n"
+ " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$<TARGET_FILE:${TARGET}>\")" "\n"
" include(\"${_GOOGLETEST_DISCOVER_TESTS_SCRIPT}\")" "\n"
" gtest_discover_tests_impl(" "\n"
" TEST_EXECUTABLE" " [==[" "$<TARGET_FILE:${TARGET}>" "]==]" "\n"
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index 2ef0489b6..967ad7bc1 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -557,7 +557,7 @@ function(cpack_deb_prepare_package_vars)
string(APPEND _description_failure_message
" or CPACK_DEBIAN_${_local_component_name}_DESCRIPTION")
endif()
- message(FATAL_ERROR _description_failure_message)
+ message(FATAL_ERROR "${_description_failure_message}")
endif()
# Ok, description has set. According to the `Debian Policy Manual`_ the first
@@ -673,7 +673,7 @@ function(cpack_deb_prepare_package_vars)
if(CPACK_ADD_LDCONFIG_CALL)
set(CPACK_DEBIAN_GENERATE_POSTINST 1)
set(CPACK_DEBIAN_GENERATE_POSTRM 1)
- foreach(f IN LISTS PACKAGE_CONTROL_EXTRA)
+ foreach(f IN LISTS CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA)
get_filename_component(n "${f}" NAME)
if(n STREQUAL "postinst")
set(CPACK_DEBIAN_GENERATE_POSTINST 0)
diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake
index 08bbc6804..47d2a5c7f 100644
--- a/Modules/Internal/CPack/CPackRPM.cmake
+++ b/Modules/Internal/CPack/CPackRPM.cmake
@@ -6,6 +6,56 @@
cmake_policy(PUSH)
cmake_policy(SET CMP0057 NEW) # if IN_LIST
+function(set_spec_script_if_enabled TYPE PACKAGE_NAME VAR)
+ if(NOT "${VAR}" STREQUAL "" AND NOT "${VAR}" STREQUAL "\n")
+ if(PACKAGE_NAME)
+ set(PACKAGE_NAME " -n ${PACKAGE_NAME}")
+ endif()
+ set(${TYPE}_
+ "%${TYPE}${PACKAGE_NAME}\n"
+ "${VAR}\n" PARENT_SCOPE)
+ else()
+ set(${TYPE} "" PARENT_SCOPE)
+ endif()
+endfunction()
+
+macro(set_spec_scripts PACKAGE_NAME)
+ # we should only set scripts that were provided
+ # as script announcement without content inside
+ # spec file will generate unneeded dependency
+ # on shell
+
+ set_spec_script_if_enabled(
+ "post"
+ "${PACKAGE_NAME}"
+ "${RPM_SYMLINK_POSTINSTALL}\n${CPACK_RPM_SPEC_POSTINSTALL}")
+
+ set_spec_script_if_enabled(
+ "posttrans"
+ "${PACKAGE_NAME}"
+ "${CPACK_RPM_SPEC_POSTTRANS}")
+
+ set_spec_script_if_enabled(
+ "postun"
+ "${PACKAGE_NAME}"
+ "${CPACK_RPM_SPEC_POSTUNINSTALL}")
+
+ set_spec_script_if_enabled(
+ "pre"
+ "${PACKAGE_NAME}"
+ "${CPACK_RPM_SPEC_PREINSTALL}")
+
+ set_spec_script_if_enabled(
+ "pretrans"
+ "${PACKAGE_NAME}"
+ "${CPACK_RPM_SPEC_PRETRANS}")
+
+ set_spec_script_if_enabled(
+ "preun"
+ "${PACKAGE_NAME}"
+ "${CPACK_RPM_SPEC_PREUNINSTALL}")
+endmacro()
+
function(get_file_permissions FILE RETURN_VAR)
execute_process(COMMAND ls -l ${FILE}
OUTPUT_VARIABLE permissions_
@@ -1024,6 +1074,21 @@ function(cpack_rpm_generate_package)
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE "\n" ";" RPMBUILD_TAG_LIST "${RPMBUILD_TAG_LIST}")
+ # In some versions of RPM, weak dependency tags are present in the --querytags
+ # list, but unsupported by rpmbuild. A different method must be used to check
+ # if they are supported.
+
+ execute_process(
+ COMMAND ${RPM_EXECUTABLE} --suggests
+ ERROR_QUIET
+ RESULT_VARIABLE RPMBUILD_SUGGESTS_RESULT)
+
+ if(NOT RPMBUILD_SUGGESTS_RESULT EQUAL 0)
+ foreach(_WEAK_DEP SUGGESTS RECOMMENDS SUPPLEMENTS ENHANCES)
+ list(REMOVE_ITEM RPMBUILD_TAG_LIST ${_WEAK_DEP})
+ endforeach()
+ endif()
+
if(CPACK_RPM_PACKAGE_EPOCH)
set(TMP_RPM_EPOCH "Epoch: ${CPACK_RPM_PACKAGE_EPOCH}")
endif()
@@ -1349,15 +1414,21 @@ function(cpack_rpm_generate_package)
continue()
endif()
- file(GLOB_RECURSE files_for_move_ LIST_DIRECTORIES false RELATIVE
+ file(GLOB_RECURSE files_for_move_ LIST_DIRECTORIES true RELATIVE
"${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}"
"${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/*")
foreach(f_ IN LISTS files_for_move_)
- get_filename_component(dir_path_ "${f_}" DIRECTORY)
set(src_file_
"${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/${f_}")
+ if(IS_DIRECTORY "${src_file_}")
+ file(MAKE_DIRECTORY "${WDIR}/${f_}")
+ continue()
+ endif()
+
+ get_filename_component(dir_path_ "${f_}" DIRECTORY)
+
# check that we are not overriding an existing file that doesn't
# match the file that we want to copy
if(EXISTS "${src_file_}" AND EXISTS "${WDIR}/${f_}")
@@ -1607,6 +1678,9 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@
)
elseif(GENERATE_SPEC_PARTS) # binary rpm with single debuginfo package
+
+ set_spec_scripts("${CPACK_RPM_PACKAGE_NAME}")
+
file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in
"# -*- rpm-spec -*-
%package -n \@CPACK_RPM_PACKAGE_NAME\@
@@ -1637,6 +1711,13 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@
%description -n \@CPACK_RPM_PACKAGE_NAME\@
\@CPACK_RPM_PACKAGE_DESCRIPTION\@
+\@post_\@
+\@posttrans_\@
+\@postun_\@
+\@pre_\@
+\@pretrans_\@
+\@preun_\@
+
%files -n \@CPACK_RPM_PACKAGE_NAME\@
%defattr(\@TMP_DEFAULT_FILE_PERMISSIONS\@,\@TMP_DEFAULT_USER\@,\@TMP_DEFAULT_GROUP\@,\@TMP_DEFAULT_DIR_PERMISSIONS\@)
\@CPACK_RPM_INSTALL_FILES\@
@@ -1662,6 +1743,8 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@
set(RPMBUILD_FLAGS "-bb")
if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE OR NOT CPACK_RPM_USER_BINARY_SPECFILE)
+ set_spec_scripts("")
+
file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in
"# Restore old style debuginfo creation for rpm >= 4.14.
%undefine _debugsource_packages
@@ -1725,24 +1808,12 @@ mv %_topdir/tmpBBroot $RPM_BUILD_ROOT
%clean
-%post
-\@RPM_SYMLINK_POSTINSTALL\@
-\@CPACK_RPM_SPEC_POSTINSTALL\@
-
-%posttrans
-\@CPACK_RPM_SPEC_POSTTRANS\@
-
-%postun
-\@CPACK_RPM_SPEC_POSTUNINSTALL\@
-
-%pre
-\@CPACK_RPM_SPEC_PREINSTALL\@
-
-%pretrans
-\@CPACK_RPM_SPEC_PRETRANS\@
-
-%preun
-\@CPACK_RPM_SPEC_PREUNINSTALL\@
+\@post_\@
+\@posttrans_\@
+\@postun_\@
+\@pre_\@
+\@pretrans_\@
+\@preun_\@
%files
%defattr(\@TMP_DEFAULT_FILE_PERMISSIONS\@,\@TMP_DEFAULT_USER\@,\@TMP_DEFAULT_GROUP\@,\@TMP_DEFAULT_DIR_PERMISSIONS\@)
diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in
index e6439ad7e..0a9c4877d 100644
--- a/Modules/Internal/CPack/NSIS.template.in
+++ b/Modules/Internal/CPack/NSIS.template.in
@@ -919,8 +919,8 @@ Function .onInit
;Run the uninstaller
uninst:
ClearErrors
- StrLen $2 "\Uninstall.exe"
- StrCpy $3 $0 -$2 # remove "\Uninstall.exe" from UninstallString to get path
+ StrLen $2 "\@CPACK_NSIS_UNINSTALL_NAME@.exe"
+ StrCpy $3 $0 -$2 # remove "\@CPACK_NSIS_UNINSTALL_NAME@.exe" from UninstallString to get path
ExecWait '"$0" /S _?=$3' ;Do not copy the uninstaller to a temp file
IfErrors uninst_failed inst
diff --git a/Modules/Internal/CheckCompilerFlag.cmake b/Modules/Internal/CheckCompilerFlag.cmake
index 99efc372e..f6a4cc962 100644
--- a/Modules/Internal/CheckCompilerFlag.cmake
+++ b/Modules/Internal/CheckCompilerFlag.cmake
@@ -13,10 +13,12 @@ function(CMAKE_CHECK_COMPILER_FLAG _lang _flag _var)
if(_lang STREQUAL "C")
set(_lang_src "int main(void) { return 0; }")
- set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C")
+ set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C"
+ FAIL_REGEX "-Werror=.* argument .* is not valid for C")
elseif(_lang STREQUAL "CXX")
set(_lang_src "int main() { return 0; }")
- set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+")
+ set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+"
+ FAIL_REGEX "-Werror=.* argument .* is not valid for C\\+\\+")
elseif(_lang STREQUAL "CUDA")
set(_lang_src "__host__ int main() { return 0; }")
set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+" # Host GNU
@@ -24,6 +26,9 @@ function(CMAKE_CHECK_COMPILER_FLAG _lang _flag _var)
elseif(_lang STREQUAL "Fortran")
set(_lang_src " program test\n stop\n end program")
set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for Fortran")
+ elseif(_lang STREQUAL "HIP")
+ set(_lang_src "__host__ int main() { return 0; }")
+ set(_lang_fail_regex FAIL_REGEX "argument unused during compilation: .*") # Clang
elseif(_lang STREQUAL "OBJC")
set(_lang_src [=[
#ifndef __OBJC__
diff --git a/Modules/Internal/CheckSourceCompiles.cmake b/Modules/Internal/CheckSourceCompiles.cmake
index 3b2152ae5..8c3a41863 100644
--- a/Modules/Internal/CheckSourceCompiles.cmake
+++ b/Modules/Internal/CheckSourceCompiles.cmake
@@ -22,6 +22,9 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var)
elseif(_lang STREQUAL "Fortran")
set(_lang_textual "Fortran")
set(_lang_ext "F90")
+ elseif(_lang STREQUAL "HIP")
+ set(_lang_textual "HIP")
+ set(_lang_ext "hip")
elseif(_lang STREQUAL "ISPC")
set(_lang_textual "ISPC")
set(_lang_ext "ispc")
diff --git a/Modules/Internal/CheckSourceRuns.cmake b/Modules/Internal/CheckSourceRuns.cmake
index 676f3d016..75e98960f 100644
--- a/Modules/Internal/CheckSourceRuns.cmake
+++ b/Modules/Internal/CheckSourceRuns.cmake
@@ -22,6 +22,9 @@ function(CMAKE_CHECK_SOURCE_RUNS _lang _source _var)
elseif(_lang STREQUAL "Fortran")
set(_lang_textual "Fortran")
set(_lang_ext "F90")
+ elseif(_lang STREQUAL "HIP")
+ set(_lang_textual "HIP")
+ set(_lang_ext "hip")
elseif(_lang STREQUAL "OBJC")
set(_lang_textual "Objective-C")
set(_lang_ext "m")
diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake
index 72d96b33f..b6f3c091d 100644
--- a/Modules/Internal/FeatureTesting.cmake
+++ b/Modules/Internal/FeatureTesting.cmake
@@ -99,6 +99,16 @@ macro(_record_compiler_features_cuda std)
unset(lang_level_has_features)
endmacro()
+macro(_record_compiler_features_hip std)
+ list(APPEND CMAKE_HIP${std}_COMPILE_FEATURES hip_std_${std})
+
+ get_property(lang_level_has_features GLOBAL PROPERTY CMAKE_HIP${std}_KNOWN_FEATURES)
+ if(lang_level_has_features)
+ _record_compiler_features(HIP "${CMAKE_HIP${std}_STANDARD_COMPILE_OPTION}" CMAKE_HIP${std}_COMPILE_FEATURES)
+ endif()
+ unset(lang_level_has_features)
+endmacro()
+
macro(_has_compiler_features lang level compile_flags feature_list)
# presume all known features are supported
get_property(known_features GLOBAL PROPERTY CMAKE_${lang}${level}_KNOWN_FEATURES)
@@ -117,3 +127,7 @@ macro(_has_compiler_features_cuda std)
list(APPEND CMAKE_CUDA${std}_COMPILE_FEATURES cuda_std_${std})
_has_compiler_features(CUDA ${std} "${CMAKE_CUDA${std}_STANDARD_COMPILE_OPTION}" CMAKE_CUDA${std}_COMPILE_FEATURES)
endmacro()
+macro(_has_compiler_features_hip std)
+ list(APPEND CMAKE_HIP${std}_COMPILE_FEATURES hip_std_${std})
+ _has_compiler_features(HIP ${std} "${CMAKE_HIP${std}_STANDARD_COMPILE_OPTION}" CMAKE_HIP${std}_COMPILE_FEATURES)
+endmacro()
diff --git a/Modules/Platform/ARTOS-GNU-C.cmake b/Modules/Platform/ARTOS-GNU-C.cmake
index fe8d782e3..bce461330 100644
--- a/Modules/Platform/ARTOS-GNU-C.cmake
+++ b/Modules/Platform/ARTOS-GNU-C.cmake
@@ -1,4 +1,4 @@
-# Define ARTOS to select proper behaviour and tell preprocessor to accept C++ style comments.
+# Define ARTOS to select proper behavior and tell preprocessor to accept C++ style comments.
string(APPEND CMAKE_C_FLAGS_INIT " -DARTOS -Xp -+")
# ac doesn't support -g properly and doesn't support the normal gcc optimization options. Just use the defaults set by ac.
string(APPEND CMAKE_C_FLAGS_DEBUG_INIT " ")
diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake
index 63bc94917..50f06209f 100644
--- a/Modules/Platform/Android-Initialize.cmake
+++ b/Modules/Platform/Android-Initialize.cmake
@@ -56,6 +56,11 @@ if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
endif()
+ # Don't search paths in PATH environment variable.
+ if(NOT DEFINED CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH)
+ set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF)
+ endif()
+
# Allows CMake to find headers in the architecture-specific include directories.
set(CMAKE_LIBRARY_ARCHITECTURE "${CMAKE_ANDROID_ARCH_TRIPLE}")
diff --git a/Modules/Platform/Apple-NVIDIA-CUDA.cmake b/Modules/Platform/Apple-NVIDIA-CUDA.cmake
index bec394839..35e759a65 100644
--- a/Modules/Platform/Apple-NVIDIA-CUDA.cmake
+++ b/Modules/Platform/Apple-NVIDIA-CUDA.cmake
@@ -1,19 +1,19 @@
include(Platform/Darwin)
-set(__IMPLICT_LINKS )
+set(__IMPLICIT_LINKS)
foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
- string(APPEND __IMPLICT_LINKS " -L\"${dir}\"")
+ string(APPEND __IMPLICIT_LINKS " -L\"${dir}\"")
endforeach()
foreach(lib ${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES})
if(${lib} MATCHES "/")
- string(APPEND __IMPLICT_LINKS " \"${lib}\"")
+ string(APPEND __IMPLICIT_LINKS " \"${lib}\"")
else()
- string(APPEND __IMPLICT_LINKS " -l${lib}")
+ string(APPEND __IMPLICIT_LINKS " -l${lib}")
endif()
endforeach()
set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS "-shared -Wl,-headerpad_max_install_names")
set(CMAKE_SHARED_MODULE_CREATE_CUDA_FLAGS "-shared -Wl,-headerpad_max_install_names")
-set(CMAKE_CUDA_CREATE_SHARED_LIBRARY "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
-set(CMAKE_CUDA_CREATE_SHARED_MODULE "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
+set(CMAKE_CUDA_CREATE_SHARED_LIBRARY "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
+set(CMAKE_CUDA_CREATE_SHARED_MODULE "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
diff --git a/Modules/Platform/CYGWIN-GNU.cmake b/Modules/Platform/CYGWIN-GNU.cmake
index 4fa14cea6..b81bd4d2b 100644
--- a/Modules/Platform/CYGWIN-GNU.cmake
+++ b/Modules/Platform/CYGWIN-GNU.cmake
@@ -10,7 +10,6 @@ set(__CYGWIN_COMPILER_GNU 1)
# TODO: Is -Wl,--enable-auto-import now always default?
string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,--enable-auto-import")
-set(CMAKE_CREATE_WIN32_EXE "-mwindows")
set(CMAKE_GNULD_IMAGE_VERSION
"-Wl,--major-image-version,<TARGET_VERSION_MAJOR>,--minor-image-version,<TARGET_VERSION_MINOR>")
@@ -23,6 +22,7 @@ macro(__cygwin_compiler_gnu lang)
"<CMAKE_${lang}_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> ${CMAKE_GNULD_IMAGE_VERSION} <OBJECTS> <LINK_LIBRARIES>")
set(CMAKE_${lang}_LINK_EXECUTABLE
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES>")
+ set(CMAKE_${lang}_CREATE_WIN32_EXE "-mwindows")
# No -fPIC on cygwin
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "")
diff --git a/Modules/Platform/CYGWIN.cmake b/Modules/Platform/CYGWIN.cmake
index 9b897bd47..fc4ea2ed5 100644
--- a/Modules/Platform/CYGWIN.cmake
+++ b/Modules/Platform/CYGWIN.cmake
@@ -1,7 +1,7 @@
-if("${CMAKE_MINIMUM_REQUIRED_VERSION}" VERSION_LESS "2.8.3.20101214")
+if("${CMAKE_MINIMUM_REQUIRED_VERSION}" VERSION_LESS "2.8.3.20101214" AND NOT MSYS)
set(__USE_CMAKE_LEGACY_CYGWIN_WIN32 1)
endif()
-if(NOT DEFINED WIN32)
+if(NOT DEFINED WIN32 AND NOT MSYS)
set(WIN32 0)
if(DEFINED __USE_CMAKE_LEGACY_CYGWIN_WIN32)
if(NOT DEFINED CMAKE_LEGACY_CYGWIN_WIN32
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index 839dc814e..d9a789475 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -47,9 +47,7 @@ set(CMAKE_SHARED_MODULE_PREFIX "lib")
set(CMAKE_SHARED_MODULE_SUFFIX ".so")
set(CMAKE_MODULE_EXISTS 1)
set(CMAKE_DL_LIBS "")
-if(NOT "${_CURRENT_OSX_VERSION}" VERSION_LESS "10.5")
- set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,")
-endif()
+set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,")
foreach(lang C CXX OBJC OBJCXX)
set(CMAKE_${lang}_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
diff --git a/Modules/Platform/Linux-Fujitsu-C.cmake b/Modules/Platform/Linux-Fujitsu-C.cmake
new file mode 100644
index 000000000..e37573dca
--- /dev/null
+++ b/Modules/Platform/Linux-Fujitsu-C.cmake
@@ -0,0 +1 @@
+include(Platform/Linux-Clang-C)
diff --git a/Modules/Platform/Linux-Fujitsu-CXX.cmake b/Modules/Platform/Linux-Fujitsu-CXX.cmake
new file mode 100644
index 000000000..5257f1383
--- /dev/null
+++ b/Modules/Platform/Linux-Fujitsu-CXX.cmake
@@ -0,0 +1 @@
+include(Platform/Linux-Clang-CXX)
diff --git a/Modules/Platform/Linux-Fujitsu.cmake b/Modules/Platform/Linux-Fujitsu.cmake
new file mode 100644
index 000000000..be11b0a9f
--- /dev/null
+++ b/Modules/Platform/Linux-Fujitsu.cmake
@@ -0,0 +1,17 @@
+# 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(__LINUX_COMPILER_FUJITSU)
+ return()
+endif()
+set(__LINUX_COMPILER_FUJITSU 1)
+
+macro(__linux_compiler_fujitsu lang)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
+ set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
+ set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
+endmacro()
diff --git a/Modules/Platform/MSYS-Clang-C.cmake b/Modules/Platform/MSYS-Clang-C.cmake
new file mode 100644
index 000000000..f025b33fa
--- /dev/null
+++ b/Modules/Platform/MSYS-Clang-C.cmake
@@ -0,0 +1 @@
+include(Platform/CYGWIN-Clang-C)
diff --git a/Modules/Platform/MSYS-Clang-CXX.cmake b/Modules/Platform/MSYS-Clang-CXX.cmake
new file mode 100644
index 000000000..e509eaad9
--- /dev/null
+++ b/Modules/Platform/MSYS-Clang-CXX.cmake
@@ -0,0 +1 @@
+include(Platform/CYGWIN-Clang-CXX)
diff --git a/Modules/Platform/MSYS-Determine-CXX.cmake b/Modules/Platform/MSYS-Determine-CXX.cmake
new file mode 100644
index 000000000..dec17f03a
--- /dev/null
+++ b/Modules/Platform/MSYS-Determine-CXX.cmake
@@ -0,0 +1 @@
+include(Platform/CYGWIN-Determine-CXX)
diff --git a/Modules/Platform/MSYS-GNU-C.cmake b/Modules/Platform/MSYS-GNU-C.cmake
new file mode 100644
index 000000000..e8343a442
--- /dev/null
+++ b/Modules/Platform/MSYS-GNU-C.cmake
@@ -0,0 +1 @@
+include(Platform/CYGWIN-GNU-C)
diff --git a/Modules/Platform/MSYS-GNU-CXX.cmake b/Modules/Platform/MSYS-GNU-CXX.cmake
new file mode 100644
index 000000000..67775deab
--- /dev/null
+++ b/Modules/Platform/MSYS-GNU-CXX.cmake
@@ -0,0 +1 @@
+include(Platform/CYGWIN-GNU-CXX)
diff --git a/Modules/Platform/MSYS-GNU-Fortran.cmake b/Modules/Platform/MSYS-GNU-Fortran.cmake
new file mode 100644
index 000000000..b0b7d8ed4
--- /dev/null
+++ b/Modules/Platform/MSYS-GNU-Fortran.cmake
@@ -0,0 +1 @@
+include(Platform/CYGWIN-GNU-Fortran)
diff --git a/Modules/Platform/MSYS-GNU.cmake b/Modules/Platform/MSYS-GNU.cmake
new file mode 100644
index 000000000..012c1120a
--- /dev/null
+++ b/Modules/Platform/MSYS-GNU.cmake
@@ -0,0 +1 @@
+include(Platform/CYGWIN-GNU)
diff --git a/Modules/Platform/MSYS-windres.cmake b/Modules/Platform/MSYS-windres.cmake
new file mode 100644
index 000000000..faaccc2ec
--- /dev/null
+++ b/Modules/Platform/MSYS-windres.cmake
@@ -0,0 +1 @@
+include(Platform/CYGWIN-windres)
diff --git a/Modules/Platform/MSYS.cmake b/Modules/Platform/MSYS.cmake
new file mode 100644
index 000000000..96fa36f58
--- /dev/null
+++ b/Modules/Platform/MSYS.cmake
@@ -0,0 +1,4 @@
+set(MSYS 1)
+include(Platform/CYGWIN)
+set(CMAKE_SHARED_LIBRARY_PREFIX "msys-")
+set(CMAKE_SHARED_MODULE_PREFIX "msys-")
diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake
index c508ac1a5..373be760d 100644
--- a/Modules/Platform/Windows-Clang.cmake
+++ b/Modules/Platform/Windows-Clang.cmake
@@ -57,8 +57,8 @@ macro(__windows_compiler_clang_gnu lang)
set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto")
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_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_APPEND_IPO "<CMAKE_AR> r <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_CREATE_IPO "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_APPEND_IPO "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_${lang}_ARCHIVE_FINISH_IPO "<CMAKE_RANLIB> <TARGET>")
# Create archiving rules to support large object file lists for static libraries.
@@ -71,8 +71,8 @@ macro(__windows_compiler_clang_gnu lang)
set(CMAKE_${lang}_LINK_EXECUTABLE
"<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES>")
- set(CMAKE_CREATE_WIN32_EXE "-Xlinker /subsystem:windows")
- set(CMAKE_CREATE_CONSOLE_EXE "-Xlinker /subsystem:console")
+ set(CMAKE_${lang}_CREATE_WIN32_EXE "-Xlinker /subsystem:windows")
+ set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-Xlinker /subsystem:console")
if(NOT "${lang}" STREQUAL "ASM")
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -Xclang -flto-visibility-public-std -D_MT -Xclang --dependent-lib=libcmt)
diff --git a/Modules/Platform/Windows-Embarcadero.cmake b/Modules/Platform/Windows-Embarcadero.cmake
index 8f1d02430..4ecc2c2c9 100644
--- a/Modules/Platform/Windows-Embarcadero.cmake
+++ b/Modules/Platform/Windows-Embarcadero.cmake
@@ -51,11 +51,6 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES "-bcc.lib" ".lib")
# Borland cannot handle + in the file name, so mangle object file name
set (CMAKE_MANGLE_OBJECT_FILE_NAMES "ON")
-# extra flags for a win32 exe
-set(CMAKE_CREATE_WIN32_EXE "${_tW}" )
-# extra flags for a console app
-set(CMAKE_CREATE_CONSOLE_EXE "${_tC}" )
-
set (CMAKE_BUILD_TYPE Debug CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel.")
@@ -124,6 +119,9 @@ macro(__embarcadero_language lang)
"tlib ${CMAKE_START_TEMP_FILE}/p512 <LINK_FLAGS> /a <TARGET_QUOTED> <OBJECTS>${CMAKE_END_TEMP_FILE}"
)
+ set(CMAKE_${lang}_CREATE_WIN32_EXE "${_tW}")
+ set(CMAKE_${lang}_CREATE_CONSOLE_EXE "${_tC}")
+
# Precompile Headers
if (EMBARCADERO)
set(CMAKE_PCH_EXTENSION .pch)
diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake
index a2e3811dd..d0003803b 100644
--- a/Modules/Platform/Windows-GNU.cmake
+++ b/Modules/Platform/Windows-GNU.cmake
@@ -35,7 +35,6 @@ set(CMAKE_LIBRARY_PATH_FLAG "-L")
set(CMAKE_LINK_LIBRARY_FLAG "-l")
set(CMAKE_LINK_DEF_FILE_FLAG "") # Empty string: passing the file is enough
set(CMAKE_LINK_LIBRARY_SUFFIX "")
-set(CMAKE_CREATE_WIN32_EXE "-mwindows")
set(CMAKE_GNULD_IMAGE_VERSION
"-Wl,--major-image-version,<TARGET_VERSION_MAJOR>,--minor-image-version,<TARGET_VERSION_MINOR>")
@@ -105,6 +104,7 @@ macro(__windows_compiler_gnu lang)
"<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> ${CMAKE_GNULD_IMAGE_VERSION} <OBJECTS> <LINK_LIBRARIES>")
set(CMAKE_${lang}_LINK_EXECUTABLE
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES>")
+ set(CMAKE_${lang}_CREATE_WIN32_EXE "-mwindows")
list(APPEND CMAKE_${lang}_ABI_FILES "Platform/Windows-GNU-${lang}-ABI")
@@ -121,7 +121,7 @@ macro(__windows_compiler_gnu lang)
CMAKE_${lang}_${rule} "${CMAKE_${lang}_${rule}}")
set(CMAKE_${lang}_${rule}
"<CMAKE_COMMAND> -E rm -f <OBJECT_DIR>/objects.a"
- "<CMAKE_AR> cr <OBJECT_DIR>/objects.a <OBJECTS>"
+ "<CMAKE_AR> qc <OBJECT_DIR>/objects.a <OBJECTS>"
"${CMAKE_${lang}_${rule}}"
)
endforeach()
diff --git a/Modules/Platform/Windows-Intel.cmake b/Modules/Platform/Windows-Intel.cmake
index 01f8dd0b1..26e0cdef4 100644
--- a/Modules/Platform/Windows-Intel.cmake
+++ b/Modules/Platform/Windows-Intel.cmake
@@ -25,8 +25,4 @@ endif()
include(Platform/Windows-MSVC)
macro(__windows_compiler_intel lang)
__windows_compiler_msvc(${lang})
- string(REPLACE "<CMAKE_AR>" "xilib" CMAKE_${lang}_CREATE_STATIC_LIBRARY "${CMAKE_${lang}_CREATE_STATIC_LIBRARY}")
- foreach(rule CREATE_SHARED_LIBRARY CREATE_SHARED_MODULE LINK_EXECUTABLE)
- string(REPLACE "<CMAKE_LINKER>" "xilink" CMAKE_${lang}_${rule} "${CMAKE_${lang}_${rule}}")
- endforeach()
endmacro()
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index e384af456..4223bde8c 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -27,12 +27,8 @@ else()
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsCE")
- set(CMAKE_CREATE_WIN32_EXE "/entry:WinMainCRTStartup")
- set(CMAKE_CREATE_CONSOLE_EXE "/entry:mainACRTStartup")
set(_PLATFORM_LINK_FLAGS " /subsystem:windowsce")
else()
- set(CMAKE_CREATE_WIN32_EXE "/subsystem:windows")
- set(CMAKE_CREATE_CONSOLE_EXE "/subsystem:console")
set(_PLATFORM_LINK_FLAGS "")
endif()
@@ -351,6 +347,14 @@ macro(__windows_compiler_msvc lang)
set(CMAKE_${lang}_LINK_EXECUTABLE
"${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
+ if(CMAKE_SYSTEM_NAME STREQUAL "WindowsCE")
+ set(CMAKE_${lang}_CREATE_WIN32_EXE "/entry:WinMainCRTStartup")
+ set(CMAKE_${lang}_CREATE_CONSOLE_EXE "/entry:mainACRTStartup")
+ else()
+ set(CMAKE_${lang}_CREATE_WIN32_EXE "/subsystem:windows")
+ set(CMAKE_${lang}_CREATE_CONSOLE_EXE "/subsystem:console")
+ endif()
+
set(CMAKE_PCH_EXTENSION .pch)
set(CMAKE_LINK_PCH ON)
if (CMAKE_${lang}_COMPILER_ID STREQUAL "Clang")
diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
index a88f4bc44..b83932edd 100644
--- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake
+++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
@@ -7,49 +7,49 @@ set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION
set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION
"<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
-set(__IMPLICT_LINKS )
+set(__IMPLICIT_LINKS)
foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
- string(APPEND __IMPLICT_LINKS " -LIBPATH:\"${dir}\"")
+ string(APPEND __IMPLICIT_LINKS " -LIBPATH:\"${dir}\"")
endforeach()
foreach(lib ${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES})
- string(APPEND __IMPLICT_LINKS " \"${lib}\"")
+ string(APPEND __IMPLICIT_LINKS " \"${lib}\"")
endforeach()
set(CMAKE_CUDA_LINK_EXECUTABLE
- "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
+ "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_LIBRARIES>${__IMPLICIT_LINKS}")
set(_CMAKE_VS_LINK_DLL "<CMAKE_COMMAND> -E vs_link_dll --intdir=<OBJECT_DIR> --rc=<CMAKE_RC_COMPILER> --mt=<CMAKE_MT> --manifests <MANIFESTS> -- ")
set(_CMAKE_VS_LINK_EXE "<CMAKE_COMMAND> -E vs_link_exe --intdir=<OBJECT_DIR> --rc=<CMAKE_RC_COMPILER> --mt=<CMAKE_MT> --manifests <MANIFESTS> -- ")
set(CMAKE_CUDA_CREATE_SHARED_LIBRARY
- "${_CMAKE_VS_LINK_DLL}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /dll /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}")
+ "${_CMAKE_VS_LINK_DLL}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /dll /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICIT_LINKS} ${CMAKE_END_TEMP_FILE}")
set(CMAKE_CUDA_CREATE_SHARED_MODULE ${CMAKE_CUDA_CREATE_SHARED_LIBRARY})
set(CMAKE_CUDA_CREATE_STATIC_LIBRARY "<CMAKE_AR> ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
set(CMAKE_CUDA_LINKER_SUPPORTS_PDB ON)
set(CMAKE_CUDA_LINK_EXECUTABLE
- "${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}")
-unset(_CMAKE_VS_LINK_EXE)
+ "${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICIT_LINKS} ${CMAKE_END_TEMP_FILE}")
+unset(_CMAKE_VS_LINK_DLL)
unset(_CMAKE_VS_LINK_EXE)
# Add implicit host link directories that contain device libraries
# to the device link line.
-set(__IMPLICT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
-if(__IMPLICT_DLINK_DIRS)
- list(REMOVE_ITEM __IMPLICT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
+set(__IMPLICIT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+if(__IMPLICIT_DLINK_DIRS)
+ list(REMOVE_ITEM __IMPLICIT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
endif()
-set(__IMPLICT_DLINK_FLAGS )
-foreach(dir ${__IMPLICT_DLINK_DIRS})
+set(__IMPLICIT_DLINK_FLAGS)
+foreach(dir ${__IMPLICIT_DLINK_DIRS})
if(EXISTS "${dir}/curand_static.lib")
- string(APPEND __IMPLICT_DLINK_FLAGS " -L\"${dir}\"")
+ string(APPEND __IMPLICIT_DLINK_FLAGS " -L\"${dir}\"")
endif()
endforeach()
-unset(__IMPLICT_DLINK_DIRS)
+unset(__IMPLICIT_DLINK_DIRS)
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICIT_DLINK_FLAGS}")
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
-unset(__IMPLICT_DLINK_FLAGS)
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICIT_DLINK_FLAGS}")
+unset(__IMPLICIT_DLINK_FLAGS)
string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}")
@@ -69,14 +69,6 @@ else()
endif()
unset(_cmp0092)
-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 "")
-
-if(UNIX)
- list(APPEND CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "rt" "pthread" "dl")
-endif()
-
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_RELEASE_INIT " -Xcompiler=\"${_MD}-O2 -Ob2\" -DNDEBUG")
diff --git a/Modules/Platform/Windows-OpenWatcom-C.cmake b/Modules/Platform/Windows-OpenWatcom-C.cmake
index ce9bc4532..b82a4cb23 100644
--- a/Modules/Platform/Windows-OpenWatcom-C.cmake
+++ b/Modules/Platform/Windows-OpenWatcom-C.cmake
@@ -1 +1,2 @@
include(Platform/Windows-OpenWatcom)
+__windows_open_watcom(C)
diff --git a/Modules/Platform/Windows-OpenWatcom-CXX.cmake b/Modules/Platform/Windows-OpenWatcom-CXX.cmake
index ce9bc4532..ac90d280b 100644
--- a/Modules/Platform/Windows-OpenWatcom-CXX.cmake
+++ b/Modules/Platform/Windows-OpenWatcom-CXX.cmake
@@ -1 +1,2 @@
include(Platform/Windows-OpenWatcom)
+__windows_open_watcom(CXX)
diff --git a/Modules/Platform/Windows-OpenWatcom.cmake b/Modules/Platform/Windows-OpenWatcom.cmake
index 70055da95..19bcb9707 100644
--- a/Modules/Platform/Windows-OpenWatcom.cmake
+++ b/Modules/Platform/Windows-OpenWatcom.cmake
@@ -6,8 +6,6 @@ include_guard()
set(CMAKE_BUILD_TYPE_INIT Debug)
-set(CMAKE_CREATE_WIN32_EXE "system nt_win" )
-set(CMAKE_CREATE_CONSOLE_EXE "system nt" )
string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT " system nt_dll")
string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT " system nt_dll")
@@ -30,3 +28,8 @@ if(CMAKE_CROSSCOMPILING)
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES $ENV{WATCOM}/h $ENV{WATCOM}/h/nt)
endif()
endif()
+
+macro(__windows_open_watcom lang)
+ set(CMAKE_${lang}_CREATE_WIN32_EXE "system nt_win")
+ set(CMAKE_${lang}_CREATE_CONSOLE_EXE "system nt")
+endmacro()
diff --git a/Modules/Platform/Windows-df.cmake b/Modules/Platform/Windows-df.cmake
index 8b824bc45..c823423a0 100644
--- a/Modules/Platform/Windows-df.cmake
+++ b/Modules/Platform/Windows-df.cmake
@@ -27,8 +27,8 @@ set(CMAKE_Fortran_COMPILE_OBJECT
set(CMAKE_Fortran_LINK_EXECUTABLE
"<CMAKE_Fortran_COMPILER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} <FLAGS> /exe:<TARGET> <OBJECTS> /link <CMAKE_Fortran_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
-set(CMAKE_CREATE_WIN32_EXE /winapp)
-set(CMAKE_CREATE_CONSOLE_EXE )
+set(CMAKE_Fortran_CREATE_WIN32_EXE /winapp)
+set(CMAKE_Fortran_CREATE_CONSOLE_EXE )
# does the compiler support pdbtype and is it the newer compiler
diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake
index 120a54c84..ef63ac34b 100644
--- a/Modules/UseJava.cmake
+++ b/Modules/UseJava.cmake
@@ -5,413 +5,545 @@
UseJava
-------
-Use Module for Java
-
-This file provides functions for Java. It is assumed that
+This file provides support for ``Java``. It is assumed that
:module:`FindJava` has already been loaded. See :module:`FindJava` for
-information on how to load Java into your CMake project.
+information on how to load Java into your ``CMake`` project.
+
+Synopsis
+^^^^^^^^
+
+.. parsed-literal::
+
+ `Creating and Installing JARS`_
+ `add_jar`_ (<target_name> [SOURCES] <source1> [<source2>...] ...)
+ `install_jar`_ (<target_name> DESTINATION <destination> [COMPONENT <component>])
+ `install_jni_symlink`_ (<target_name> DESTINATION <destination> [COMPONENT <component>])
+
+ `Header Generation`_
+ `create_javah`_ ((TARGET <target> | GENERATED_FILES <VAR>) CLASSES <class>... ...)
+
+ `Exporting JAR Targets`_
+ `install_jar_exports`_ (TARGETS <jars>... FILE <filename> DESTINATION <destination> ...)
+ `export_jars`_ (TARGETS <jars>... [NAMESPACE <namespace>] FILE <filename>)
+
+ `Finding JARs`_
+ `find_jar`_ (<VAR> NAMES <name1> [<name2>...] [PATHS <path1> [<path2>... ENV <var>]] ...)
+
+ `Creating Java Documentation`_
+ `create_javadoc`_ (<VAR> (PACKAGES <pkg1> [<pkg2>...] | FILES <file1> [<file2>...]) ...)
Creating And Installing JARs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. code-block:: cmake
-
- add_jar(<target_name>
- [SOURCES] <source1> [<source2>...] [<resource1>...]
- [INCLUDE_JARS <jar1> [<jar2>...]]
- [ENTRY_POINT <entry>]
- [VERSION <version>]
- [OUTPUT_NAME <name>]
- [OUTPUT_DIR <dir>]
- [GENERATE_NATIVE_HEADERS <target>
- [DESTINATION (<dir>|INSTALL <dir> [BUILD <dir>])]]
- )
-
-This command creates a ``<target_name>.jar``. It compiles the given
-``<source>`` files and adds the given ``<resource>`` files to
-the jar file. Source files can be java files or listing files
-(prefixed by ``@``). If only resource files are given then just a jar file
-is created. The list of ``INCLUDE_JARS`` are added to the classpath when
-compiling the java sources and also to the dependencies of the target.
-``INCLUDE_JARS`` also accepts other target names created by ``add_jar()``.
-For backwards compatibility, jar files listed as sources are ignored (as
-they have been since the first version of this module).
-
-.. versionadded:: 3.4
- Support for response files (prefixed by ``@``) in the ``SOURCES`` list.
-
-The default ``OUTPUT_DIR`` can also be changed by setting the variable
-``CMAKE_JAVA_TARGET_OUTPUT_DIR``.
-
-.. versionadded:: 3.11
- Optionally, using option ``GENERATE_NATIVE_HEADERS``, native header files can
- be generated for methods declared as native. These files provide the
- connective glue that allow your Java and C code to interact. An INTERFACE
- target will be created for an easy usage of generated files. Sub-option
- ``DESTINATION`` can be used to specify the output directory for generated
- header files.
-
- ``GENERATE_NATIVE_HEADERS`` option requires, at least, version 1.8 of the JDK.
-
-.. versionadded:: 3.20
- ``DESTINATION`` sub-option now supports the possibility to specify different
- output directories for ``BUILD`` and ``INSTALL`` steps. This is required to
- export the interface target generated by ``GENERATE_NATIVE_HEADERS`` option.
- If ``BUILD`` directory is not specified, a default directory will be used.
-
-The ``add_jar()`` function sets the following target properties on
-``<target_name>``:
-
-``INSTALL_FILES``
- The files which should be installed. This is used by ``install_jar()``.
-``JNI_SYMLINK``
- The JNI symlink which should be installed. This is used by
- ``install_jni_symlink()``.
-``JAR_FILE``
- The location of the jar file so that you can include it.
-``CLASSDIR``
- The directory where the class files can be found. For example to use them
- with ``javah``.
-
-.. versionadded:: 3.20
- The target generated by option ``GENERATE_NATIVE_HEADERS`` has the property
- ``NATIVE_HEADERS_DIRECTORY`` which specify the directory holding the native
- headers.
-
-.. code-block:: cmake
-
- install_jar(<target_name> <destination>)
- install_jar(<target_name> DESTINATION <destination> [COMPONENT <component>])
-
-This command installs the ``<target_name>`` files to the given
-``<destination>``. It should be called in the same scope as ``add_jar()`` or
-it will fail.
-
-The ``install_jar()`` function sets the ``INSTALL_DESTINATION`` target
-property on jars so installed. This property holds the ``<destination>`` as
-described above, and is used by ``install_jar_exports()``. You can get this
-information with :command:`get_property` and the ``INSTALL_DESTINATION``
-property key.
-
-.. versionadded:: 3.4
- The second signature with ``DESTINATION`` and ``COMPONENT`` options.
-
-.. code-block:: cmake
-
- install_jni_symlink(<target_name> <destination>)
- install_jni_symlink(<target_name> DESTINATION <destination> [COMPONENT <component>])
-
-This command installs the ``<target_name>`` JNI symlinks to the given
-``<destination>``. It should be called in the same scope as ``add_jar()`` or
-it will fail.
-
-.. versionadded:: 3.4
- The second signature with ``DESTINATION`` and ``COMPONENT`` options.
+.. _add_jar:
-Exporting JAR Targets
-^^^^^^^^^^^^^^^^^^^^^
+.. command:: add_jar
-.. versionadded:: 3.7
+ Creates a jar file containing java objects and, optionally, resources::
-.. code-block:: cmake
+ add_jar(<target_name>
+ [SOURCES] <source1> [<source2>...] [<resource1>...]
+ [RESOURCES NAMESPACE <ns1> <resource1>... [NAMESPACE <nsX> <resourceX>...]... ]
+ [INCLUDE_JARS <jar1> [<jar2>...]]
+ [ENTRY_POINT <entry>]
+ [VERSION <version>]
+ [MANIFEST <manifest>]
+ [OUTPUT_NAME <name>]
+ [OUTPUT_DIR <dir>]
+ [GENERATE_NATIVE_HEADERS <target>
+ [DESTINATION (<dir>|INSTALL <dir> [BUILD <dir>])]]
+ )
- install_jar_exports(TARGETS <jars>...
- [NAMESPACE <namespace>]
- FILE <filename>
- DESTINATION <destination> [COMPONENT <component>])
+ This command creates a ``<target_name>.jar``. It compiles the given
+ ``<source>`` files and adds the given ``<resource>`` files to
+ the jar file. Source files can be java files or listing files
+ (prefixed by ``@``). If only resource files are given then just a jar file
+ is created.
-This command installs a target export file ``<filename>`` for the named jar
-targets to the given ``<destination>`` directory. Its function is similar to
-that of :command:`install(EXPORTS)`.
+ ``SOURCES``
+ Compiles the specified source files and adds the result in the jar file.
-.. versionadded:: 3.9
- The ``NAMESPACE`` option.
+ .. versionadded:: 3.4
+ Support for response files, prefixed by ``@``.
-.. code-block:: cmake
+ ``RESOURCES``
+ .. versionadded:: 3.21
- export_jars(TARGETS <jars>...
- [NAMESPACE <namespace>]
- FILE <filename>)
+ Adds the named ``<resource>`` files to the jar by stripping the source file
+ path and placing the file beneath ``<ns>`` within the jar.
-This command writes a target export file ``<filename>`` for the named ``<jars>``
-targets. Its function is similar to that of :command:`export`.
+ For example::
-.. versionadded:: 3.9
- The ``NAMESPACE`` option.
+ RESOURCES NAMESPACE "/com/my/namespace" "a/path/to/resource.txt"
+ results in a resource accessible via ``/com/my/namespace/resource.txt``
+ within the jar.
-Examples
-""""""""
+ Resources may be added without adjusting the namespace by adding them to
+ the list of ``SOURCES`` (original behavior), in this case, resource
+ paths must be relative to ``CMAKE_CURRENT_SOURCE_DIR``. Adding resources
+ without using the ``RESOURCES`` parameter in out of source builds will
+ almost certainly result in confusion.
-To add compile flags to the target you can set these flags with the following
-variable:
+ .. note::
-.. code-block:: cmake
+ Adding resources via the ``SOURCES`` parameter relies upon a hard-coded
+ list of file extensions which are tested to determine whether they
+ compile (e.g. File.java). ``SOURCES`` files which match the extensions
+ are compiled. Files which do not match are treated as resources. To
+ include uncompiled resources matching those file extensions use
+ the ``RESOURCES`` parameter.
- set(CMAKE_JAVA_COMPILE_FLAGS -nowarn)
+ ``INCLUDE_JARS``
+ The list of jars are added to the classpath when compiling the java sources
+ and also to the dependencies of the target. ``INCLUDE_JARS`` also accepts
+ other target names created by ``add_jar()``. For backwards compatibility,
+ jar files listed as sources are ignored (as they have been since the first
+ version of this module).
+ ``ENTRY_POINT``
+ Defines an entry point in the jar file.
-To add a path or a jar file to the class path you can do this with the
-``CMAKE_JAVA_INCLUDE_PATH`` variable.
+ ``VERSION``
+ Adds a version to the target output name.
-.. code-block:: cmake
+ The following example will create a jar file with the name
+ ``shibboleet-1.2.0.jar`` and will create a symlink ``shibboleet.jar``
+ pointing to the jar with the version information.
- set(CMAKE_JAVA_INCLUDE_PATH /usr/share/java/shibboleet.jar)
+ .. code-block:: cmake
-To use a different output name for the target you can set it with:
+ add_jar(shibboleet shibbotleet.java VERSION 1.2.0)
-.. code-block:: cmake
+ ``MANIFEST``
+ Defines a custom manifest for the jar.
- add_jar(foobar foobar.java OUTPUT_NAME shibboleet.jar)
+ ``OUTPUT_NAME``
+ Specify a different output name for the target.
-To use a different output directory than ``CMAKE_CURRENT_BINARY_DIR`` you can
-set it with:
+ ``OUTPUT_DIR``
+ Sets the directory where the jar file will be generated. If not specified,
+ :variable:`CMAKE_CURRENT_BINARY_DIR` is used as the output directory.
-.. code-block:: cmake
+ ``GENERATE_NATIVE_HEADERS``
+ .. versionadded:: 3.11
- add_jar(foobar foobar.java OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin)
+ Generates native header files for methods declared as native. These files
+ provide the connective glue that allow your Java and C code to interact.
+ An INTERFACE target will be created for an easy usage of generated files.
+ Sub-option ``DESTINATION`` can be used to specify the output directory for
+ generated header files.
-To define an entry point in your jar you can set it with the ``ENTRY_POINT``
-named argument:
+ This option requires, at least, version 1.8 of the JDK.
-.. code-block:: cmake
+ For an optimum usage of this option, it is recommended to include module
+ JNI before any call to ``add_jar()``. The produced target for native
+ headers can then be used to compile C/C++ sources with the
+ :command:`target_link_libraries` command.
- add_jar(example ENTRY_POINT com/examples/MyProject/Main)
+ .. code-block:: cmake
-To define a custom manifest for the jar, you can set it with the ``MANIFEST``
-named argument:
+ find_package(JNI)
+ add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native)
+ add_library(bar bar.cpp)
+ target_link_libraries(bar PRIVATE foo-native)
-.. code-block:: cmake
+ .. versionadded:: 3.20
+ ``DESTINATION`` sub-option now supports the possibility to specify
+ different output directories for ``BUILD`` and ``INSTALL`` steps. If
+ ``BUILD`` directory is not specified, a default directory will be used.
- add_jar(example MANIFEST /path/to/manifest)
+ To export the interface target generated by ``GENERATE_NATIVE_HEADERS``
+ option, sub-option ``INSTALL`` of ``DESTINATION`` is required:
-To add a version to the target output name you can set it using the ``VERSION``
-named argument to ``add_jar()``. The following example will create a jar file
-with the name ``shibboleet-1.0.0.jar`` and will create a symlink
-``shibboleet.jar`` pointing to the jar with the version information.
+ .. code-block:: cmake
-.. code-block:: cmake
+ add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native
+ DESTINATION INSTALL include)
+ install(TARGETS foo-native EXPORT native)
+ install(DIRECTORY "$<TARGET_PROPERTY:foo-native,NATIVE_HEADERS_DIRECTORY>/"
+ DESTINATION include)
+ install(EXPORT native DESTINATION /to/export NAMESPACE foo)
- add_jar(shibboleet shibbotleet.java VERSION 1.2.0)
+ Some variables can be set to customize the behavior of ``add_jar()`` as well
+ as the java compiler:
-If the target is a JNI library, utilize the following commands to
-create a JNI symbolic link:
+ ``CMAKE_JAVA_COMPILE_FLAGS``
+ Specify additional flags to java compiler.
-.. code-block:: cmake
+ ``CMAKE_JAVA_INCLUDE_PATH``
+ Specify additional paths to the class path.
- set(CMAKE_JNI_TARGET TRUE)
- add_jar(shibboleet shibbotleet.java VERSION 1.2.0)
- install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet)
- install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR})
+ ``CMAKE_JNI_TARGET``
+ If the target is a JNI library, sets this boolean variable to ``TRUE`` to
+ enable creation of a JNI symbolic link (see also
+ :ref:`install_jni_symlink() <install_jni_symlink>`).
-If a single target needs to produce more than one jar from its
-java source code, to prevent the accumulation of duplicate class
-files in subsequent jars, set/reset ``CMAKE_JAR_CLASSES_PREFIX`` prior
-to calling the ``add_jar()`` function:
+ ``CMAKE_JAR_CLASSES_PREFIX``
+ If multiple jars should be produced from the same java source filetree,
+ to prevent the accumulation of duplicate class files in subsequent jars,
+ set/reset ``CMAKE_JAR_CLASSES_PREFIX`` prior to calling the ``add_jar()``:
-.. code-block:: cmake
+ .. code-block:: cmake
- set(CMAKE_JAR_CLASSES_PREFIX com/redhat/foo)
- add_jar(foo foo.java)
+ set(CMAKE_JAR_CLASSES_PREFIX com/redhat/foo)
+ add_jar(foo foo.java)
- set(CMAKE_JAR_CLASSES_PREFIX com/redhat/bar)
- add_jar(bar bar.java)
+ set(CMAKE_JAR_CLASSES_PREFIX com/redhat/bar)
+ add_jar(bar bar.java)
-For an optimum usage of option ``GENERATE_NATIVE_HEADERS``, it is recommended to
-include module JNI before any call to ``add_jar()``. The produced target for
-native headers can then be used to compile C/C++ sources with the
-:command:`target_link_libraries` command.
+ The ``add_jar()`` function sets the following target properties on
+ ``<target_name>``:
-.. code-block:: cmake
+ ``INSTALL_FILES``
+ The files which should be installed. This is used by
+ :ref:`install_jar() <install_jar>`.
+ ``JNI_SYMLINK``
+ The JNI symlink which should be installed. This is used by
+ :ref:`install_jni_symlink() <install_jni_symlink>`.
+ ``JAR_FILE``
+ The location of the jar file so that you can include it.
+ ``CLASSDIR``
+ The directory where the class files can be found. For example to use them
+ with ``javah``.
+ ``NATIVE_HEADERS_DIRECTORY``
+ .. versionadded:: 3.20
- find_package(JNI)
- add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native)
- add_library(bar bar.cpp)
- target_link_libraries(bar PRIVATE foo-native)
+ The directory where native headers are generated. Defined when option
+ ``GENERATE_NATIVE_HEADERS`` is specified.
-.. versionadded:: 3.20
- It is now possible to export the target generated by
- ``GENERATE_NATIVE_HEADERS`` option.
+.. _install_jar:
- .. code-block:: cmake
+.. command:: install_jar
- add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native
- DESTINATION INSTALL include)
- install(TARGETS foo-native EXPORT native)
- install(DIRECTORY "$<TARGET_PROPERTY:foo-native,NATIVE_HEADERS_DIRECTORY>/"
- DESTINATION include)
- install(EXPORT native DESTINATION /to/export NAMESPACE foo)
+ This command installs the jar file to the given destination::
-Finding JARs
-^^^^^^^^^^^^
+ install_jar(<target_name> <destination>)
+ install_jar(<target_name> DESTINATION <destination> [COMPONENT <component>])
-.. code-block:: cmake
-
- find_jar(<VAR>
- <name> | NAMES <name1> [<name2>...]
- [PATHS <path1> [<path2>... ENV <var>]]
- [VERSIONS <version1> [<version2>]]
- [DOC "cache documentation string"]
- )
-
-This command is used to find a full path to the named jar. A cache
-entry named by ``<VAR>`` is created to store the result of this command.
-If the full path to a jar is found the result is stored in the
-variable and the search will not repeated unless the variable is
-cleared. If nothing is found, the result will be ``<VAR>-NOTFOUND``, and
-the search will be attempted again next time ``find_jar()`` is invoked with
-the same variable. The name of the full path to a file that is
-searched for is specified by the names listed after ``NAMES`` argument.
-Additional search locations can be specified after the ``PATHS`` argument.
-If you require special a version of a jar file you can specify it with
-the ``VERSIONS`` argument. The argument after ``DOC`` will be used for the
-documentation string in the cache.
-
-
-Javadoc
-^^^^^^^
-
-The ``create_javadoc()`` command can be used to create java documentation
-based on files or packages. For more details please read the javadoc manpage.
-
-There are two main signatures for ``create_javadoc()``. The first signature
-works with package names on a path with source files.
-
-.. code-block:: cmake
-
- create_javadoc(<VAR>
- PACKAGES <pkg1> [<pkg2>...]
- [SOURCEPATH <sourcepath>]
- [CLASSPATH <classpath>]
- [INSTALLPATH <install path>]
- [DOCTITLE "the documentation title"]
- [WINDOWTITLE "the title of the document"]
- [AUTHOR TRUE|FALSE]
- [USE TRUE|FALSE]
- [VERSION TRUE|FALSE]
- )
+ This command installs the ``<target_name>`` file to the given
+ ``<destination>``. It should be called in the same scope as
+ :ref:`add_jar() <add_jar>` or it will fail.
-For example:
-
-.. code-block:: cmake
-
- create_javadoc(my_example_doc
- PACKAGES com.example.foo com.example.bar
- SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}"
- CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
- WINDOWTITLE "My example"
- DOCTITLE "<h1>My example</h1>"
- AUTHOR TRUE
- USE TRUE
- VERSION TRUE
- )
-
-The second signature for ``create_javadoc()`` works on a given list of
-files.
-
-.. code-block:: cmake
-
- create_javadoc(<VAR>
- FILES <file1> [<file2>...]
- [CLASSPATH <classpath>]
- [INSTALLPATH <install path>]
- [DOCTITLE "the documentation title"]
- [WINDOWTITLE "the title of the document"]
- [AUTHOR TRUE|FALSE]
- [USE TRUE|FALSE]
- [VERSION TRUE|FALSE]
- )
+ .. versionadded:: 3.4
+ The second signature with ``DESTINATION`` and ``COMPONENT`` options.
+
+ ``DESTINATION``
+ Specify the directory on disk to which a file will be installed.
+
+ ``COMPONENT``
+ Specify an installation component name with which the install rule is
+ associated, such as "runtime" or "development".
+
+ The ``install_jar()`` command sets the following target properties
+ on ``<target_name>``:
+
+ ``INSTALL_DESTINATION``
+ Holds the ``<destination>`` as described above, and is used by
+ :ref:`install_jar_exports() <install_jar_exports>`.
+
+.. _install_jni_symlink:
-For example:
+.. command:: install_jni_symlink
-.. code-block:: cmake
+ Installs JNI symlinks for target generated by :ref:`add_jar() <add_jar>`::
- create_javadoc(my_example_doc
- FILES ${example_SRCS}
- CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
- WINDOWTITLE "My example"
- DOCTITLE "<h1>My example</h1>"
- AUTHOR TRUE
- USE TRUE
- VERSION TRUE
- )
+ install_jni_symlink(<target_name> <destination>)
+ install_jni_symlink(<target_name> DESTINATION <destination> [COMPONENT <component>])
-Both signatures share most of the options. These options are the same
-as what you can find in the javadoc manpage. Please look at the
-manpage for ``CLASSPATH``, ``DOCTITLE``, ``WINDOWTITLE``, ``AUTHOR``, ``USE``
-and ``VERSION``.
+ This command installs the ``<target_name>`` JNI symlinks to the given
+ ``<destination>``. It should be called in the same scope as
+ :ref:`add_jar() <add_jar>` or it will fail.
-If you don't set the ``INSTALLPATH``, then by default the documentation will
-be installed to :
+ .. versionadded:: 3.4
+ The second signature with ``DESTINATION`` and ``COMPONENT`` options.
-::
+ ``DESTINATION``
+ Specify the directory on disk to which a file will be installed.
- ${CMAKE_INSTALL_PREFIX}/share/javadoc/<VAR>
+ ``COMPONENT``
+ Specify an installation component name with which the install rule is
+ associated, such as "runtime" or "development".
+ Utilize the following commands to create a JNI symbolic link:
+
+ .. code-block:: cmake
+
+ set(CMAKE_JNI_TARGET TRUE)
+ add_jar(shibboleet shibbotleet.java VERSION 1.2.0)
+ install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet)
+ install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR})
Header Generation
^^^^^^^^^^^^^^^^^
-.. code-block:: cmake
+.. _create_javah:
+
+.. command:: create_javah
+
+ .. versionadded:: 3.4
+
+ Generates C header files for java classes::
+
+ create_javah(TARGET <target> | GENERATED_FILES <VAR>
+ CLASSES <class>...
+ [CLASSPATH <classpath>...]
+ [DEPENDS <depend>...]
+ [OUTPUT_NAME <path>|OUTPUT_DIR <path>]
+ )
+
+ .. 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>`_.
+ The :ref:`add_jar(GENERATE_NATIVE_HEADERS) <add_jar>` command should be
+ used instead.
+
+ Create C header files from java classes. These files provide the connective
+ glue that allow your Java and C code to interact.
+
+ There are two main signatures for ``create_javah()``. The first signature
+ returns generated files through variable specified by the ``GENERATED_FILES``
+ option. For example:
+
+ .. code-block:: cmake
+
+ create_javah(GENERATED_FILES files_headers
+ CLASSES org.cmake.HelloWorld
+ CLASSPATH hello.jar
+ )
+
+ The second signature for ``create_javah()`` creates a target which
+ encapsulates header files generation. E.g.
+
+ .. code-block:: cmake
+
+ create_javah(TARGET target_headers
+ CLASSES org.cmake.HelloWorld
+ CLASSPATH hello.jar
+ )
+
+ Both signatures share same options.
+
+ ``CLASSES``
+ Specifies Java classes used to generate headers.
+
+ ``CLASSPATH``
+ Specifies various paths to look up classes. Here ``.class`` files, jar
+ files or targets created by command add_jar can be used.
+
+ ``DEPENDS``
+ Targets on which the javah target depends.
+
+ ``OUTPUT_NAME``
+ Concatenates the resulting header files for all the classes listed by
+ option ``CLASSES`` into ``<path>``. Same behavior as option ``-o`` of
+ ``javah`` tool.
+
+ ``OUTPUT_DIR``
+ Sets the directory where the header files will be generated. Same behavior
+ as option ``-d`` of ``javah`` tool. If not specified,
+ :variable:`CMAKE_CURRENT_BINARY_DIR` is used as the output directory.
+
+Exporting JAR Targets
+^^^^^^^^^^^^^^^^^^^^^
+
+.. _install_jar_exports:
+
+.. command:: install_jar_exports
+
+ .. versionadded:: 3.7
+
+ Installs a target export file::
- create_javah(TARGET <target> | GENERATED_FILES <VAR>
- CLASSES <class>...
- [CLASSPATH <classpath>...]
- [DEPENDS <depend>...]
- [OUTPUT_NAME <path>|OUTPUT_DIR <path>]
- )
+ install_jar_exports(TARGETS <jars>...
+ [NAMESPACE <namespace>]
+ FILE <filename>
+ DESTINATION <destination> [COMPONENT <component>])
-.. versionadded:: 3.4
+ This command installs a target export file ``<filename>`` for the named jar
+ targets to the given ``<destination>`` directory. Its function is similar to
+ that of :command:`install(EXPORT)`.
-.. 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>`_.
- The ``add_jar(GENERATE_NATIVE_HEADERS)`` command should be used instead.
+ ``TARGETS``
+ List of targets created by :ref:`add_jar() <add_jar>` command.
-Create C header files from java classes. These files provide the connective glue
-that allow your Java and C code to interact.
+ ``NAMESPACE``
+ .. versionadded:: 3.9
-There are two main signatures for ``create_javah()``. The first signature
-returns generated files through variable specified by the ``GENERATED_FILES``
-option. For example:
+ The ``<namespace>`` value will be prepend to the target names as they are
+ written to the import file.
-.. code-block:: cmake
+ ``FILE``
+ Specify name of the export file.
- create_javah(GENERATED_FILES files_headers
- CLASSES org.cmake.HelloWorld
- CLASSPATH hello.jar
- )
-The second signature for ``create_javah()`` creates a target which encapsulates
-header files generation. E.g.
+ ``DESTINATION``
+ Specify the directory on disk to which a file will be installed.
-.. code-block:: cmake
+ ``COMPONENT``
+ Specify an installation component name with which the install rule is
+ associated, such as "runtime" or "development".
- create_javah(TARGET target_headers
- CLASSES org.cmake.HelloWorld
- CLASSPATH hello.jar
- )
+.. _export_jars:
-Both signatures share same options.
+.. command:: export_jars
-``CLASSES <class>...``
- Specifies Java classes used to generate headers.
+ .. versionadded:: 3.7
-``CLASSPATH <classpath>...``
- Specifies various paths to look up classes. Here .class files, jar files or
- targets created by command add_jar can be used.
+ Writes a target export file::
-``DEPENDS <depend>...``
- Targets on which the javah target depends.
+ export_jars(TARGETS <jars>...
+ [NAMESPACE <namespace>]
+ FILE <filename>)
-``OUTPUT_NAME <path>``
- Concatenates the resulting header files for all the classes listed by option
- ``CLASSES`` into ``<path>``. Same behavior as option ``-o`` of javah tool.
+ This command writes a target export file ``<filename>`` for the named ``<jars>``
+ targets. Its function is similar to that of :command:`export`.
-``OUTPUT_DIR <path>``
- Sets the directory where the header files will be generated. Same behavior
- as option ``-d`` of javah tool. If not specified,
- :variable:`CMAKE_CURRENT_BINARY_DIR` is used as the output directory.
+ ``TARGETS``
+ List of targets created by :ref:`add_jar() <add_jar>` command.
+
+ ``NAMESPACE``
+ .. versionadded:: 3.9
+
+ The ``<namespace>`` value will be prepend to the target names as they are
+ written to the import file.
+
+ ``FILE``
+ Specify name of the export file.
+
+Finding JARs
+^^^^^^^^^^^^
+
+.. _find_jar:
+
+.. command:: find_jar
+
+ Finds the specified jar file::
+
+ find_jar(<VAR>
+ <name> | NAMES <name1> [<name2>...]
+ [PATHS <path1> [<path2>... ENV <var>]]
+ [VERSIONS <version1> [<version2>]]
+ [DOC "cache documentation string"]
+ )
+
+ This command is used to find a full path to the named jar. A cache
+ entry named by ``<VAR>`` is created to store the result of this command.
+ If the full path to a jar is found the result is stored in the
+ variable and the search will not repeated unless the variable is
+ cleared. If nothing is found, the result will be ``<VAR>-NOTFOUND``, and
+ the search will be attempted again next time ``find_jar()`` is invoked with
+ the same variable.
+
+ ``NAMES``
+ Specify one or more possible names for the jar file.
+
+ ``PATHS``
+ Specify directories to search in addition to the default locations.
+ The ``ENV`` var sub-option reads paths from a system environment variable.
+
+ ``VERSIONS``
+ Specify jar versions.
+
+ ``DOC``
+ Specify the documentation string for the ``<VAR>`` cache entry.
+
+Creating Java Documentation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. _create_javadoc:
+
+.. command:: create_javadoc
+
+ Creates java documentation based on files and packages::
+
+ create_javadoc(<VAR>
+ (PACKAGES <pkg1> [<pkg2>...] | FILES <file1> [<file2>...])
+ [SOURCEPATH <sourcepath>]
+ [CLASSPATH <classpath>]
+ [INSTALLPATH <install path>]
+ [DOCTITLE <the documentation title>]
+ [WINDOWTITLE <the title of the document>]
+ [AUTHOR (TRUE|FALSE)]
+ [USE (TRUE|FALSE)]
+ [VERSION (TRUE|FALSE)]
+ )
+
+ The ``create_javadoc()`` command can be used to create java documentation.
+ There are two main signatures for ``create_javadoc()``.
+
+ The first signature works with package names on a path with source files:
+
+ .. code-block:: cmake
+
+ create_javadoc(my_example_doc
+ PACKAGES com.example.foo com.example.bar
+ SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}"
+ CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
+ WINDOWTITLE "My example"
+ DOCTITLE "<h1>My example</h1>"
+ AUTHOR TRUE
+ USE TRUE
+ VERSION TRUE
+ )
+
+ The second signature for ``create_javadoc()`` works on a given list of files:
+
+ .. code-block:: cmake
+
+ create_javadoc(my_example_doc
+ FILES java/A.java java/B.java
+ CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
+ WINDOWTITLE "My example"
+ DOCTITLE "<h1>My example</h1>"
+ AUTHOR TRUE
+ USE TRUE
+ VERSION TRUE
+ )
+
+ Both signatures share most of the options. For more details please read the
+ javadoc manpage.
+
+ ``PACKAGES``
+ Specify java packages.
+
+ ``FILES``
+ Specify java source files. If relative paths are specified, they are
+ relative to :variable:`CMAKE_CURRENT_SOURCE_DIR`.
+
+ ``SOURCEPATH``
+ Specify the directory where to look for packages. By default,
+ :variable:`CMAKE_CURRENT_SOURCE_DIR` directory is used.
+
+ ``CLASSPATH``
+ Specify where to find user class files. Same behavior as option
+ ``-classpath`` of ``javadoc`` tool.
+
+ ``INSTALLPATH``
+ Specify where to install the java documentation. If you specified, the
+ documentation will be installed to
+ ``${CMAKE_INSTALL_PREFIX}/share/javadoc/<VAR>``.
+
+ ``DOCTITLE``
+ Specify the title to place near the top of the overview summary file.
+ Same behavior as option ``-doctitle`` of ``javadoc`` tool.
+
+ ``WINDOWTITLE``
+ Specify the title to be placed in the HTML ``<title>`` tag. Same behavior
+ as option ``-windowtitle`` of ``javadoc`` tool.
+
+ ``AUTHOR``
+ When value ``TRUE`` is specified, includes the ``@author`` text in the
+ generated docs. Same behavior as option ``-author`` of ``javadoc`` tool.
+
+ ``USE``
+ When value ``TRUE`` is specified, creates class and package usage pages.
+ Includes one Use page for each documented class and package. Same behavior
+ as option ``-use`` of ``javadoc`` tool.
+
+ ``VERSION``
+ When value ``TRUE`` is specified, includes the version text in the
+ generated docs. Same behavior as option ``-version`` of ``javadoc`` tool.
#]=======================================================================]
function (__java_copy_file src dest comment)
@@ -449,6 +581,58 @@ function(__java_export_jar VAR TARGET PATH)
set(${VAR} "${${VAR}}" PARENT_SCOPE)
endfunction()
+function(__java_copy_resource_namespaces VAR DEST JAVA_RESOURCE_FILES JAVA_RESOURCE_FILES_RELATIVE)
+
+ set(_ns_ID "")
+ set(_ns_VAL "")
+
+ foreach(_item IN LISTS VAR)
+ if(NOT _ns_ID)
+ if(NOT _item STREQUAL "NAMESPACE")
+ message(FATAL_ERROR "UseJava: Expecting \"NAMESPACE\", got\t\"${_item}\"")
+ return()
+ endif()
+ endif()
+
+ if(_item STREQUAL "NAMESPACE")
+ set(_ns_VAL "") # Prepare for next namespace
+ set(_ns_ID "${_item}")
+ continue()
+ endif()
+
+ if( NOT _ns_VAL)
+ # we're expecting the next token to be a namespace value
+ # whatever it is, we're treating it like a namespace
+ set(_ns_VAL "${_item}")
+ continue()
+ endif()
+
+ if(_ns_ID AND _ns_VAL)
+ # We're expecting a file name, check to see if we got one
+ cmake_path(ABSOLUTE_PATH _item OUTPUT_VARIABLE _test_file_name)
+ if (NOT EXISTS "${_test_file_name}")
+ message(FATAL_ERROR "UseJava: File does not exist:\t${_item}")
+ return()
+ endif()
+ endif()
+
+ cmake_path(ABSOLUTE_PATH _item OUTPUT_VARIABLE _abs_file_name)
+ cmake_path(GET _item FILENAME _resource_file_name)
+ set(_dest_resource_file_name "${_ns_VAL}/${_resource_file_name}" )
+
+ __java_copy_file( ${_abs_file_name}
+ ${DEST}/${_dest_resource_file_name}
+ "Copying ${_item} to the build directory")
+
+ list(APPEND RESOURCE_FILES_LIST ${DEST}/${_dest_resource_file_name})
+ list(APPEND RELATIVE_RESOURCE_FILES_LIST ${_dest_resource_file_name})
+
+ endforeach()
+
+ set(${JAVA_RESOURCE_FILES} "${RESOURCE_FILES_LIST}" PARENT_SCOPE)
+ set(${JAVA_RESOURCE_FILES_RELATIVE} "${RELATIVE_RESOURCE_FILES_LIST}" PARENT_SCOPE)
+endfunction()
+
# define helper scripts
set(_JAVA_EXPORT_TARGETS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/javaTargets.cmake.in)
set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/Symlinks.cmake)
@@ -461,12 +645,14 @@ endif()
function(add_jar _TARGET_NAME)
- cmake_parse_arguments(_add_jar
- ""
- "VERSION;OUTPUT_DIR;OUTPUT_NAME;ENTRY_POINT;MANIFEST"
- "SOURCES;INCLUDE_JARS;GENERATE_NATIVE_HEADERS"
- ${ARGN}
- )
+ set(options) # currently there are no zero value args (aka: options)
+ set(oneValueArgs "ENTRY_POINT;MANIFEST;OUTPUT_DIR;;OUTPUT_NAME;VERSION" )
+ set(multiValueArgs "GENERATE_NATIVE_HEADERS;INCLUDE_JARS;RESOURCES;SOURCES" )
+
+ cmake_parse_arguments(PARSE_ARGV 1 _add_jar
+ "${options}"
+ "${oneValueArgs}"
+ "${multiValueArgs}" )
# In CMake < 2.8.12, add_jar used variables which were set prior to calling
# add_jar for customizing the behavior of add_jar. In order to be backwards
@@ -490,6 +676,9 @@ function(add_jar _TARGET_NAME)
set(_add_jar_ENTRY_POINT "${CMAKE_JAVA_JAR_ENTRY_POINT}")
endif()
+ # This *should* still work if <resources1>... are included without a
+ # named RESOURCES argument. In that case, the old behavior of potentially
+ # misplacing the within the Jar will behave as previously (incorrectly)
set(_JAVA_SOURCE_FILES ${_add_jar_SOURCES} ${_add_jar_UNPARSED_ARGUMENTS})
if (NOT DEFINED _add_jar_OUTPUT_DIR)
@@ -639,6 +828,13 @@ function(add_jar _TARGET_NAME)
endif ()
endforeach()
+ if(_add_jar_RESOURCES) # Process RESOURCES if it exists
+ __java_copy_resource_namespaces("${_add_jar_RESOURCES}"
+ ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
+ _JAVA_RESOURCE_FILES
+ _JAVA_RESOURCE_FILES_RELATIVE)
+ endif()
+
foreach(_JAVA_INCLUDE_JAR IN LISTS _add_jar_INCLUDE_JARS)
if (TARGET ${_JAVA_INCLUDE_JAR})
get_target_property(_JAVA_JAR_PATH ${_JAVA_INCLUDE_JAR} JAR_FILE)
diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake
index 60731253d..5c8f152bb 100644
--- a/Modules/UseSWIG.cmake
+++ b/Modules/UseSWIG.cmake
@@ -38,7 +38,13 @@ Defines the following command for use with ``SWIG``:
.. versionchanged:: 3.15
Alternate library name (set with the :prop_tgt:`OUTPUT_NAME` property,
- for example) will be passed on to Python and CSharp wrapper libraries.
+ for example) will be passed on to ``Python`` and ``CSharp`` wrapper
+ libraries.
+
+ .. versionchanged:: 3.21
+ Generated library use standard naming conventions for ``CSharp`` language
+ when policy :policy:`CMP0122` is set to ``NEW``. Otherwise, the legacy
+ behavior is applied.
.. note::
@@ -185,8 +191,12 @@ ensure generated files will receive the required settings.
If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool
itself. This property is only meaningful for
- :ref:`Makefile <Makefile Generators>` and
- :ref:`Ninja <Ninja Generators>` generators. Default value is ``FALSE``.
+ :ref:`Makefile <Makefile Generators>`,
+ :ref:`Ninja <Ninja Generators>` and :generator:`Xcode` generators. Default
+ value is ``FALSE``.
+
+ .. versionadded:: 3.21
+ Added the support of :generator:`Xcode` generator.
``SWIG_MODULE_NAME``
Specify the actual import name of the module in the target language.
@@ -330,12 +340,17 @@ as well as ``SWIG``:
.. versionadded:: 3.20
If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool
- itself. This property is only meaningful for
- :ref:`Makefile <Makefile Generators>` and
- :ref:`Ninja <Ninja Generators>` generators. Default value is ``FALSE``.
+ itself. This variable is only meaningful for
+ :ref:`Makefile <Makefile Generators>`,
+ :ref:`Ninja <Ninja Generators>` and :generator:`Xcode` generators. Default
+ value is ``FALSE``.
Source file property ``USE_SWIG_DEPENDENCIES``, if not defined, will be
initialized with the value of this variable.
+
+ .. versionadded:: 3.21
+ Added the support of :generator:`Xcode` generator.
+
#]=======================================================================]
cmake_policy(PUSH)
@@ -500,7 +515,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
endif()
set (use_swig_dependencies ${SWIG_USE_SWIG_DEPENDENCIES})
- if (CMAKE_GENERATOR MATCHES "Make|Ninja")
+ if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode")
get_property(use_swig_dependencies_set SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES SET)
if (use_swig_dependencies_set)
get_property(use_swig_dependencies SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES)
@@ -515,7 +530,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
endif()
set (property "$<TARGET_PROPERTY:${target_name},SWIG_INCLUDE_DIRECTORIES>")
list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:$<TARGET_GENEX_EVAL:${target_name},${property}>,$<SEMICOLON>-I>>")
- set (property "$<TARGET_PROPERTY:${target_name},INCLUDE_DIRECTORIES>")
+ set (property "$<REMOVE_DUPLICATES:$<TARGET_PROPERTY:${target_name},INCLUDE_DIRECTORIES>>")
get_source_file_property(use_target_include_dirs "${infile}" USE_TARGET_INCLUDE_DIRECTORIES)
if (use_target_include_dirs)
list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
@@ -825,7 +840,7 @@ function(SWIG_ADD_LIBRARY name)
set(SWIG_SOURCE_FILE_EXTENSIONS ".i")
endif()
- if (CMAKE_GENERATOR MATCHES "Make|Ninja")
+ if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode")
# For Makefiles and Ninja generators, use SWIG generated dependencies
if (NOT DEFINED SWIG_USE_SWIG_DEPENDENCIES)
set (SWIG_USE_SWIG_DEPENDENCIES OFF)
@@ -952,6 +967,17 @@ function(SWIG_ADD_LIBRARY name)
endif ()
elseif (swig_lowercase_language STREQUAL "fortran")
# Do *not* override the target's library prefix
+ elseif (swig_lowercase_language STREQUAL "csharp")
+ cmake_policy(GET CMP0122 csharp_naming_policy)
+ if (csharp_naming_policy STREQUAL "NEW")
+ # Do *not* override the target's library prefix
+ else()
+ if (NOT csharp_naming_policy)
+ cmake_policy(GET_WARNING CMP0122 _cmp0122_warning)
+ message(AUTHOR_WARNING "${_cmp0122_warning}\n")
+ endif()
+ set_target_properties (${target_name} PROPERTIES PREFIX "")
+ endif()
else()
# assume empty prefix because we expect the module to be dynamically loaded
set_target_properties (${target_name} PROPERTIES PREFIX "")
diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake
index 0e4e02805..54eb40ed2 100644
--- a/Modules/WriteCompilerDetectionHeader.cmake
+++ b/Modules/WriteCompilerDetectionHeader.cmake
@@ -384,6 +384,7 @@ elseif(_WCDH_policy STREQUAL "")
)
endif()
+set(__skip_rocmclang TRUE)
include(${CMAKE_CURRENT_LIST_DIR}/CMakeCompilerIdDetection.cmake)
function(_load_compiler_variables CompilerId lang)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 6adc9cf6a..9a18184fd 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -44,7 +44,7 @@ endif()
if(NOT CMake_DEFAULT_RECURSION_LIMIT)
if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST})
set(CMake_DEFAULT_RECURSION_LIMIT 100)
- elseif(MINGW)
+ elseif(MINGW OR MSYS)
set(CMake_DEFAULT_RECURSION_LIMIT 400)
elseif(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM")
set(CMake_DEFAULT_RECURSION_LIMIT 600)
@@ -198,6 +198,8 @@ set(SRCS
cmCMakePath.cxx
cmCMakePresetsFile.cxx
cmCMakePresetsFile.h
+ cmCMakePresetsFileInternal.h
+ cmCMakePresetsFileReadJSON.cxx
cmCommandArgumentParserHelper.cxx
cmCommonTargetGenerator.cxx
cmCommonTargetGenerator.h
@@ -343,11 +345,19 @@ set(SRCS
cmGraphVizWriter.h
cmInstallGenerator.h
cmInstallGenerator.cxx
+ cmInstallGetRuntimeDependenciesGenerator.h
+ cmInstallGetRuntimeDependenciesGenerator.cxx
cmInstallExportGenerator.cxx
cmInstalledFile.h
cmInstalledFile.cxx
cmInstallFilesGenerator.h
cmInstallFilesGenerator.cxx
+ cmInstallImportedRuntimeArtifactsGenerator.h
+ cmInstallImportedRuntimeArtifactsGenerator.cxx
+ cmInstallRuntimeDependencySet.h
+ cmInstallRuntimeDependencySet.cxx
+ cmInstallRuntimeDependencySetGenerator.h
+ cmInstallRuntimeDependencySetGenerator.cxx
cmInstallScriptGenerator.h
cmInstallScriptGenerator.cxx
cmInstallSubdirectoryGenerator.h
@@ -636,6 +646,7 @@ set(SRCS
cmMathCommand.h
cmMessageCommand.cxx
cmMessageCommand.h
+ cmMessageMetadata.h
cmOptionCommand.cxx
cmOptionCommand.h
cmOutputRequiredFilesCommand.cxx
@@ -785,8 +796,6 @@ if (WIN32)
cmVisualStudioGeneratorOptions.cxx
cmVisualStudio10TargetGenerator.h
cmVisualStudio10TargetGenerator.cxx
- cmVisualStudio10ToolsetOptions.h
- cmVisualStudio10ToolsetOptions.cxx
cmLocalVisualStudio10Generator.cxx
cmLocalVisualStudio10Generator.h
cmGlobalVisualStudio10Generator.h
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 61668f488..a783d052d 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 20)
-set(CMake_VERSION_PATCH 6)
+set(CMake_VERSION_MINOR 21)
+set(CMake_VERSION_PATCH 0)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
@@ -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 [==[0d3bfda22a CMake 3.20.6]==])
+ set(git_info [==[ff7a2e37bf CMake 3.21.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]* "
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx
index c4bd7f115..1429c4670 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.cxx
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -7,6 +7,8 @@
#include <sstream>
#include <utility>
+#include <cm/string_view>
+
#include "cmCPackComponentGroup.h"
#include "cmCPackIFWCommon.h"
#include "cmCPackIFWGenerator.h"
@@ -30,44 +32,67 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct() = default;
cmCPackIFWPackage::DependenceStruct::DependenceStruct(
const std::string& dependence)
{
- // Search compare section
- size_t pos = std::string::npos;
- if ((pos = dependence.find("<=")) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual;
- this->Compare.Value = dependence.substr(pos + 2);
- } else if ((pos = dependence.find(">=")) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual;
- this->Compare.Value = dependence.substr(pos + 2);
- } else if ((pos = dependence.find('<')) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareLess;
- this->Compare.Value = dependence.substr(pos + 1);
- } else if ((pos = dependence.find('=')) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareEqual;
- this->Compare.Value = dependence.substr(pos + 1);
- } else if ((pos = dependence.find('>')) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareGreater;
- this->Compare.Value = dependence.substr(pos + 1);
- } else if ((pos = dependence.find('-')) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareNone;
- this->Compare.Value = dependence.substr(pos + 1);
- }
- size_t dashPos = dependence.find('-');
- if (dashPos != std::string::npos) {
- pos = dashPos;
- }
- this->Name = dependence.substr(0, pos);
+ // Preferred format is name and version are separated by a colon (:), but
+ // note that this is only supported with QtIFW 3.1 or later. Backward
+ // compatibility allows a hyphen (-) as a separator instead, but names then
+ // cannot contain a hyphen.
+ size_t pos;
+ if ((pos = dependence.find(':')) == std::string::npos) {
+ pos = dependence.find('-');
+ }
+
+ if (pos != std::string::npos) {
+ this->Name = dependence.substr(0, pos);
+ ++pos;
+ if (pos == dependence.size()) {
+ // Nothing after the separator. Treat this as no version constraint.
+ return;
+ }
+
+ const auto versionPart =
+ cm::string_view(dependence.data() + pos, dependence.size() - pos);
+
+ if (cmHasLiteralPrefix(versionPart, "<=")) {
+ this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual;
+ this->Compare.Value = std::string(versionPart.substr(2));
+ } else if (cmHasLiteralPrefix(versionPart, ">=")) {
+ this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual;
+ this->Compare.Value = std::string(versionPart.substr(2));
+ } else if (cmHasPrefix(versionPart, '<')) {
+ this->Compare.Type = cmCPackIFWPackage::CompareLess;
+ this->Compare.Value = std::string(versionPart.substr(1));
+ } else if (cmHasPrefix(versionPart, '=')) {
+ this->Compare.Type = cmCPackIFWPackage::CompareEqual;
+ this->Compare.Value = std::string(versionPart.substr(1));
+ } else if (cmHasPrefix(versionPart, '>')) {
+ this->Compare.Type = cmCPackIFWPackage::CompareGreater;
+ this->Compare.Value = std::string(versionPart.substr(1));
+ } else {
+ // We found no operator but a version specification is still expected to
+ // follow. The default behavior is to treat this the same as =. We
+ // explicitly record that as our type (it simplifies our logic a little
+ // and is also clearer).
+ this->Compare.Type = cmCPackIFWPackage::CompareEqual;
+ this->Compare.Value = std::string(versionPart);
+ }
+ } else {
+ this->Name = dependence;
+ }
}
std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const
{
- if (this->Compare.Type == cmCPackIFWPackage::CompareNone) {
- return this->Name;
- }
-
std::string result = this->Name;
-
- if (this->Compare.Type != cmCPackIFWPackage::CompareNone ||
- !this->Compare.Value.empty()) {
+ if (this->Name.find('-') != std::string::npos) {
+ // When a name contains a hyphen, we must use a colon after the name to
+ // prevent the hyphen from being parsed by QtIFW as the separator between
+ // the name and the version. Note that a colon is only supported with
+ // QtIFW 3.1 or later.
+ result += ":";
+ } else if (this->Compare.Type != cmCPackIFWPackage::CompareNone ||
+ !this->Compare.Value.empty()) {
+ // No hyphen in the name and we know a version part will follow. Use a
+ // hyphen as a separator since this works for all QtIFW versions.
result += "-";
}
@@ -609,6 +634,9 @@ void cmCPackIFWPackage::GeneratePackageFile()
}
// Dependencies
+ const bool hyphensInNamesUnsupported = this->Generator &&
+ !this->Generator->FrameworkVersion.empty() && this->IsVersionLess("3.1");
+ bool warnUnsupportedNames = false;
std::set<DependenceStruct> compDepSet;
for (DependenceStruct* ad : this->AlienDependencies) {
compDepSet.insert(*ad);
@@ -620,9 +648,13 @@ void cmCPackIFWPackage::GeneratePackageFile()
if (!compDepSet.empty()) {
std::ostringstream dependencies;
auto it = compDepSet.begin();
+ warnUnsupportedNames |=
+ hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
dependencies << it->NameWithCompare();
++it;
while (it != compDepSet.end()) {
+ warnUnsupportedNames |=
+ hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
dependencies << "," << it->NameWithCompare();
++it;
}
@@ -638,15 +670,28 @@ void cmCPackIFWPackage::GeneratePackageFile()
if (!compAutoDepSet.empty()) {
std::ostringstream dependencies;
auto it = compAutoDepSet.begin();
+ warnUnsupportedNames |=
+ hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
dependencies << it->NameWithCompare();
++it;
while (it != compAutoDepSet.end()) {
+ warnUnsupportedNames |=
+ hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
dependencies << "," << it->NameWithCompare();
++it;
}
xout.Element("AutoDependOn", dependencies.str());
}
+ if (warnUnsupportedNames) {
+ cmCPackIFWLogger(
+ WARNING,
+ "The dependencies for component \""
+ << this->Name << "\" specify names that contain hyphens. "
+ << "This requires QtIFW 3.1 or later, but you are using version "
+ << this->Generator->FrameworkVersion << std::endl);
+ }
+
// Licenses (copy to meta dir)
std::vector<std::string> licenses = this->Licenses;
for (size_t i = 1; i < licenses.size(); i += 2) {
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
index 751f7dc3a..d7e534a70 100644
--- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
+++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
@@ -79,7 +79,7 @@ void cmWIXRichTextFormatWriter::WriteHeader()
ControlWord("ansi");
ControlWord("ansicpg1252");
ControlWord("deff0");
- ControlWord("deflang1031");
+ ControlWord("deflang1033");
WriteFontTable();
WriteColorTable();
@@ -94,7 +94,7 @@ void cmWIXRichTextFormatWriter::WriteFontTable()
StartGroup();
ControlWord("f0");
ControlWord("fswiss");
- ControlWord("fcharset0 Arial;");
+ ControlWord("fcharset0 Consolas;");
EndGroup();
EndGroup();
@@ -130,7 +130,7 @@ void cmWIXRichTextFormatWriter::WriteDocumentPrefix()
ControlWord("uc1");
ControlWord("pard");
ControlWord("f0");
- ControlWord("fs20");
+ ControlWord("fs14");
}
void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword)
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 7fd12dd4c..d9234e666 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -2,14 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackArchiveGenerator.h"
+#include <cstdlib>
#include <cstring>
#include <map>
#include <ostream>
#include <utility>
#include <vector>
-#include <cm3p/archive.h>
-
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
@@ -154,15 +153,9 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
<< (filename) << ">." << std::endl); \
return 0; \
} \
- cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat); \
+ cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat, 0, \
+ this->GetThreadCount()); \
do { \
- if (!this->SetArchiveOptions(&archive)) { \
- cmCPackLogger(cmCPackLog::LOG_ERROR, \
- "Problem to set archive options <" \
- << (filename) << ">, ERROR = " << (archive).GetError() \
- << std::endl); \
- return 0; \
- } \
if (!archive.Open()) { \
cmCPackLogger(cmCPackLog::LOG_ERROR, \
"Problem to open archive <" \
@@ -346,26 +339,16 @@ bool cmCPackArchiveGenerator::SupportsComponentInstallation() const
return this->IsOn("CPACK_ARCHIVE_COMPONENT_INSTALL");
}
-bool cmCPackArchiveGenerator::SetArchiveOptions(cmArchiveWrite* archive)
+int cmCPackArchiveGenerator::GetThreadCount() const
{
-#if ARCHIVE_VERSION_NUMBER >= 3004000
- // Upstream fixed an issue with their integer parsing in 3.4.0 which would
- // cause spurious errors to be raised from `strtoull`.
- if (this->Compress == cmArchiveWrite::CompressXZ) {
- const char* threads = "1";
-
- // CPACK_ARCHIVE_THREADS overrides CPACK_THREADS
- if (this->IsSet("CPACK_ARCHIVE_THREADS")) {
- threads = this->GetOption("CPACK_ARCHIVE_THREADS");
- } else if (this->IsSet("CPACK_THREADS")) {
- threads = this->GetOption("CPACK_THREADS");
- }
+ int threads = 1;
- if (!archive->SetFilterOption("xz", "threads", threads)) {
- return false;
- }
+ // CPACK_ARCHIVE_THREADS overrides CPACK_THREADS
+ if (this->IsSet("CPACK_ARCHIVE_THREADS")) {
+ threads = std::atoi(this->GetOption("CPACK_ARCHIVE_THREADS"));
+ } else if (this->IsSet("CPACK_THREADS")) {
+ threads = std::atoi(this->GetOption("CPACK_THREADS"));
}
-#endif
- return true;
+ return threads;
}
diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h
index 5b40013b4..8a9bbc66b 100644
--- a/Source/CPack/cmCPackArchiveGenerator.h
+++ b/Source/CPack/cmCPackArchiveGenerator.h
@@ -85,7 +85,7 @@ private:
return this->OutputExtension.c_str();
}
- bool SetArchiveOptions(cmArchiveWrite* archive);
+ int GetThreadCount() const;
private:
cmArchiveWrite::Compress Compress;
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index e7bcfaca4..006d66d3b 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -130,11 +130,6 @@ DebGenerator::DebGenerator(
"Unrecognized number of threads: " << numThreads
<< std::endl);
}
-
- if (this->NumThreads < 0) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Number of threads cannot be negative" << std::endl);
- }
}
bool DebGenerator::generate() const
@@ -172,7 +167,6 @@ void DebGenerator::generateControlFile() const
unsigned long totalSize = 0;
{
- std::string dirName = cmStrCat(this->TemporaryDir, '/');
for (std::string const& file : this->PackageFiles) {
totalSize += cmSystemTools::FileLength(file);
}
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index cefb906bb..b71c96982 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -273,6 +273,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
? this->GetOption("CPACK_DMG_FORMAT")
: "UDZO";
+ const std::string cpack_dmg_filesystem =
+ this->GetOption("CPACK_DMG_FILESYSTEM")
+ ? this->GetOption("CPACK_DMG_FILESYSTEM")
+ : "HFS+";
+
// Get optional arguments ...
std::string cpack_license_file =
this->GetOption("CPACK_RESOURCE_FILE_LICENSE")
@@ -319,7 +324,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
staging << src_dir;
// Add a symlink to /Applications so users can drag-and-drop the bundle
- // into it unless this behaviour was disabled
+ // into it unless this behavior was disabled
if (!cpack_dmg_disable_applications_symlink) {
std::ostringstream application_link;
application_link << staging.str() << "/Applications";
@@ -418,7 +423,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
temp_image_command << " -ov";
temp_image_command << " -srcfolder \"" << staging.str() << "\"";
temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\"";
- temp_image_command << " -fs HFS+";
+ temp_image_command << " -fs \"" << cpack_dmg_filesystem << "\"";
temp_image_command << " -format " << temp_image_format;
temp_image_command << " \"" << temp_image << "\"";
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 3db4162c9..00e274d6d 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -384,7 +384,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
for (std::string const& gf : this->files) {
bool skip = false;
std::string inFile = gf;
- if (cmSystemTools::FileIsDirectory(gf)) {
+ if (cmSystemTools::FileIsDirectory(gf) &&
+ !cmSystemTools::FileIsSymlink(gf)) {
inFile += '/';
}
for (cmsys::RegularExpression& reg : ignoreFilesRegex) {
@@ -693,7 +694,7 @@ int cmCPackGenerator::RunPreinstallTarget(
// Does this generator require pre-install?
if (const char* preinstall = globalGenerator->GetPreinstallTargetName()) {
std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand(
- preinstall, buildConfig, "", false);
+ preinstall, buildConfig, "", "", false);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Install command: " << buildCommand << std::endl);
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
@@ -901,6 +902,23 @@ int cmCPackGenerator::InstallCMakeProject(
this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) {
mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
}
+
+ std::vector<std::string> custom_variables;
+ this->MakefileMap->GetDefExpandList("CPACK_CUSTOM_INSTALL_VARIABLES",
+ custom_variables);
+
+ for (auto const& custom_variable : custom_variables) {
+ std::string value;
+
+ auto i = custom_variable.find('=');
+
+ if (i != std::string::npos) {
+ value = custom_variable.substr(i + 1);
+ }
+
+ mf.AddDefinition(custom_variable.substr(0, i), value);
+ }
+
// do installation
bool res = mf.ReadListFile(installFile);
// forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index f1cc67747..6bd0d1b2a 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -437,7 +437,9 @@ int cmCPackNSISGenerator::InitializeInternal()
}
#endif
- nsisPath = cmSystemTools::FindProgram("makensis", path, false);
+ this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLE", "makensis");
+ nsisPath = cmSystemTools::FindProgram(
+ this->GetOption("CPACK_NSIS_EXECUTABLE"), path, false);
if (nsisPath.empty()) {
cmCPackLogger(
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index 3e36e8cc1..ad0a3e21b 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -51,15 +51,16 @@ int cmCPackSTGZGenerator::PackageFiles()
* so we must iterate over generated packages.
*/
for (std::string const& pfn : this->packageFileNames) {
- retval &= cmSystemTools::SetPermissions(pfn.c_str(),
+ retval &= static_cast<bool>(
+ cmSystemTools::SetPermissions(pfn.c_str(),
#if defined(_MSC_VER) || defined(__MINGW32__)
- S_IREAD | S_IWRITE | S_IEXEC
+ S_IREAD | S_IWRITE | S_IEXEC
#else
- S_IRUSR | S_IWUSR | S_IXUSR |
- S_IRGRP | S_IWGRP | S_IXGRP |
- S_IROTH | S_IWOTH | S_IXOTH
+ S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
+ S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH |
+ S_IXOTH
#endif
- );
+ ));
}
return retval;
}
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 85c13ada7..a77893903 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -341,7 +341,7 @@ int main(int argc, char const* const* argv)
cmMakefile* mf = &globalMF;
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"Specified generator: " << gen << std::endl);
- if (parsed && !mf->GetDefinition("CPACK_PACKAGE_NAME")) {
+ if (!mf->GetDefinition("CPACK_PACKAGE_NAME")) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"CPack project name not specified" << std::endl);
parsed = 0;
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index a18cbb49b..adfc8ef77 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -19,6 +19,8 @@
#include "cmWorkingDirectory.h"
#include "cmake.h"
+struct cmMessageMetadata;
+
cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
{
this->BuildTwoConfig = false;
@@ -125,7 +127,7 @@ public:
: CM(cm)
{
cmSystemTools::SetMessageCallback(
- [&s](const std::string& msg, const char* /*unused*/) {
+ [&s](const std::string& msg, const cmMessageMetadata& /* unused */) {
s += msg;
s += "\n";
});
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 88e287160..483c316a6 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -27,6 +27,7 @@ void cmCTestBuildCommand::BindArguments()
this->Bind("CONFIGURATION"_s, this->Configuration);
this->Bind("FLAGS"_s, this->Flags);
this->Bind("PROJECT_NAME"_s, this->ProjectName);
+ this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel);
}
cmCTestBuildCommand::~cmCTestBuildCommand() = default;
@@ -98,8 +99,8 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
std::string dir = this->CTest->GetCTestConfiguration("BuildDirectory");
std::string buildCommand =
this->GlobalGenerator->GenerateCMakeBuildCommand(
- cmakeBuildTarget, cmakeBuildConfiguration, cmakeBuildAdditionalFlags,
- this->Makefile->IgnoreErrorsCMP0061());
+ cmakeBuildTarget, cmakeBuildConfiguration, this->ParallelLevel,
+ cmakeBuildAdditionalFlags, this->Makefile->IgnoreErrorsCMP0061());
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"SetMakeCommand:" << buildCommand << "\n",
this->Quiet);
diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h
index 00dbcc451..1254dad9b 100644
--- a/Source/CTest/cmCTestBuildCommand.h
+++ b/Source/CTest/cmCTestBuildCommand.h
@@ -60,4 +60,5 @@ protected:
std::string Configuration;
std::string Flags;
std::string ProjectName;
+ std::string ParallelLevel;
};
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 103dc1ed8..03caa6372 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -3,7 +3,6 @@
#include "cmCTestBuildHandler.h"
#include <cstdlib>
-#include <cstring>
#include <set>
#include <utility>
@@ -657,14 +656,14 @@ bool cmCTestBuildHandler::IsLaunchedErrorFile(const char* fname)
{
// error-{hash}.xml
return (cmHasLiteralPrefix(fname, "error-") &&
- strcmp(fname + strlen(fname) - 4, ".xml") == 0);
+ cmHasLiteralSuffix(fname, ".xml"));
}
bool cmCTestBuildHandler::IsLaunchedWarningFile(const char* fname)
{
// warning-{hash}.xml
return (cmHasLiteralPrefix(fname, "warning-") &&
- strcmp(fname + strlen(fname) - 4, ".xml") == 0);
+ cmHasLiteralSuffix(fname, ".xml"));
}
//######################################################################
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 3d7d0312b..57b1ddaf5 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -289,6 +289,13 @@ int cmCTestCoverageHandler::ProcessHandler()
this->CTest->GetCTestConfiguration("SourceDirectory");
std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory");
+ if (binaryDir.empty()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Binary directory is not set. "
+ "No coverage checking will be performed."
+ << std::endl);
+ return 0;
+ }
this->LoadLabels();
cmGeneratedFileStream ofs;
diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
index 051c117ca..af495bb56 100644
--- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
+++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
@@ -16,7 +16,7 @@ bool cmCTestEmptyBinaryDirectoryCommand::InitialPass(
return false;
}
- if (!cmCTestScriptHandler::EmptyBinaryDirectory(args[0].c_str())) {
+ if (!cmCTestScriptHandler::EmptyBinaryDirectory(args[0])) {
std::ostringstream ostr;
ostr << "problem removing the binary directory: " << args[0];
this->SetError(ostr.str());
diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index 91818bb2e..cc756d7dc 100644
--- a/Source/CTest/cmCTestGenericHandler.cxx
+++ b/Source/CTest/cmCTestGenericHandler.cxx
@@ -21,32 +21,47 @@ cmCTestGenericHandler::cmCTestGenericHandler()
cmCTestGenericHandler::~cmCTestGenericHandler() = default;
-void cmCTestGenericHandler::SetOption(const std::string& op, const char* value)
+/* Modify the given `map`, setting key `op` to `value` if `value`
+ * is non-null, otherwise removing key `op` (if it exists).
+ */
+static void SetMapValue(cmCTestGenericHandler::t_StringToString& map,
+ const std::string& op, const char* value)
{
if (!value) {
- auto remit = this->Options.find(op);
- if (remit != this->Options.end()) {
- this->Options.erase(remit);
- }
+ map.erase(op);
return;
}
- this->Options[op] = value;
+ map[op] = value;
+}
+
+void cmCTestGenericHandler::SetOption(const std::string& op, const char* value)
+{
+ SetMapValue(this->Options, op, value);
}
void cmCTestGenericHandler::SetPersistentOption(const std::string& op,
const char* value)
{
this->SetOption(op, value);
- if (!value) {
- auto remit = this->PersistentOptions.find(op);
- if (remit != this->PersistentOptions.end()) {
- this->PersistentOptions.erase(remit);
- }
- return;
+ SetMapValue(this->PersistentOptions, op, value);
+}
+
+void cmCTestGenericHandler::AddMultiOption(const std::string& op,
+ const std::string& value)
+{
+ if (!value.empty()) {
+ this->MultiOptions[op].emplace_back(value);
}
+}
- this->PersistentOptions[op] = value;
+void cmCTestGenericHandler::AddPersistentMultiOption(const std::string& op,
+ const std::string& value)
+{
+ if (!value.empty()) {
+ this->MultiOptions[op].emplace_back(value);
+ this->PersistentMultiOptions[op].emplace_back(value);
+ }
}
void cmCTestGenericHandler::Initialize()
@@ -68,6 +83,17 @@ const char* cmCTestGenericHandler::GetOption(const std::string& op)
return remit->second.c_str();
}
+std::vector<std::string> cmCTestGenericHandler::GetMultiOption(
+ const std::string& optionName) const
+{
+ // Avoid inserting a key, which MultiOptions[op] would do.
+ auto remit = this->MultiOptions.find(optionName);
+ if (remit == this->MultiOptions.end()) {
+ return {};
+ }
+ return remit->second;
+}
+
bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part,
const char* name,
cmGeneratedFileStream& xofs)
diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h
index 89d75968e..e846fd956 100644
--- a/Source/CTest/cmCTestGenericHandler.h
+++ b/Source/CTest/cmCTestGenericHandler.h
@@ -13,7 +13,6 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
-class cmCTestCommand;
class cmGeneratedFileStream;
class cmMakefile;
@@ -72,12 +71,40 @@ public:
virtual ~cmCTestGenericHandler();
using t_StringToString = std::map<std::string, std::string>;
+ using t_StringToMultiString =
+ std::map<std::string, std::vector<std::string>>;
+ /**
+ * Options collect a single value from flags; passing the
+ * flag multiple times on the command-line *overwrites* values,
+ * and only the last one specified counts. Set an option to
+ * nullptr to "unset" it.
+ *
+ * The value is stored as a string. The values set for single
+ * and multi-options (see below) live in different spaces,
+ * so calling a single-getter for a key that has only been set
+ * as a multi-value will return nullptr.
+ */
void SetPersistentOption(const std::string& op, const char* value);
void SetOption(const std::string& op, const char* value);
const char* GetOption(const std::string& op);
- void SetCommand(cmCTestCommand* command) { this->Command = command; }
+ /**
+ * Multi-Options collect one or more values from flags; passing
+ * the flag multiple times on the command-line *adds* values,
+ * rather than overwriting the previous values.
+ *
+ * Adding an empty value does nothing.
+ *
+ * The value is stored as a vector of strings. The values set for single
+ * (see above) and multi-options live in different spaces,
+ * so calling a multi-getter for a key that has only been set
+ * as a single-value will return an empty vector.
+ */
+ void AddPersistentMultiOption(const std::string& optionName,
+ const std::string& value);
+ void AddMultiOption(const std::string& optionName, const std::string& value);
+ std::vector<std::string> GetMultiOption(const std::string& op) const;
void SetSubmitIndex(int idx) { this->SubmitIndex = idx; }
int GetSubmitIndex() { return this->SubmitIndex; }
@@ -100,8 +127,9 @@ protected:
cmCTest* CTest;
t_StringToString Options;
t_StringToString PersistentOptions;
+ t_StringToMultiString MultiOptions;
+ t_StringToMultiString PersistentMultiOptions;
t_StringToString LogFileNames;
- cmCTestCommand* Command;
int SubmitIndex;
};
diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx
index d0e297452..37b362872 100644
--- a/Source/CTest/cmCTestMemCheckCommand.cxx
+++ b/Source/CTest/cmCTestMemCheckCommand.cxx
@@ -14,7 +14,7 @@ void cmCTestMemCheckCommand::BindArguments()
this->Bind("DEFECT_COUNT"_s, this->DefectCount);
}
-cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler()
+cmCTestTestHandler* cmCTestMemCheckCommand::InitializeActualHandler()
{
cmCTestMemCheckHandler* handler = this->CTest->GetMemCheckHandler();
handler->Initialize();
diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h
index 6544f16cf..ee39e49a9 100644
--- a/Source/CTest/cmCTestMemCheckCommand.h
+++ b/Source/CTest/cmCTestMemCheckCommand.h
@@ -13,6 +13,7 @@
#include "cmCommand.h"
class cmCTestGenericHandler;
+class cmCTestTestHandler;
/** \class cmCTestMemCheck
* \brief Run a ctest script
@@ -36,7 +37,7 @@ public:
protected:
void BindArguments() override;
- cmCTestGenericHandler* InitializeActualHandler() override;
+ cmCTestTestHandler* InitializeActualHandler() override;
void ProcessAdditionalValues(cmCTestGenericHandler* handler) override;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 852f9d91d..86a8e00a6 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -587,24 +587,24 @@ void cmCTestMultiProcessHandler::StartNextTests()
onlyRunSerialTestsLeft = false;
}
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, ");
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "***** WAITING, ");
if (this->SerialTestRunning) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Waiting for RUN_SERIAL test to finish.");
} else if (onlyRunSerialTestsLeft) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Only RUN_SERIAL tests remain, awaiting available slot.");
} else {
/* clang-format off */
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"System Load: " << systemLoad << ", "
"Max Allowed Load: " << this->TestLoad << ", "
"Smallest test " << testWithMinProcessors <<
" requires " << minProcessorsRequired);
/* clang-format on */
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "*****" << std::endl);
// Wait between 1 and 5 seconds before trying again.
unsigned int milliseconds = (cmSystemTools::RandomSeed() % 5 + 1) * 1000;
diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx
index f59ca57de..7661d4dd6 100644
--- a/Source/CTest/cmCTestRunScriptCommand.cxx
+++ b/Source/CTest/cmCTestRunScriptCommand.cxx
@@ -37,8 +37,8 @@ bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args,
++i;
} else {
int ret;
- cmCTestScriptHandler::RunScript(this->CTest, this->Makefile,
- args[i].c_str(), !np, &ret);
+ cmCTestScriptHandler::RunScript(this->CTest, this->Makefile, args[i],
+ !np, &ret);
this->Makefile->AddDefinition(returnVariable, std::to_string(ret));
}
}
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 5a6c77539..a8921134b 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -40,6 +40,22 @@ void cmCTestRunTest::CheckOutput(std::string const& line)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
this->GetIndex() << ": " << line << std::endl);
+
+ // Check for special CTest XML tags in this line of output.
+ // If any are found, this line is excluded from ProcessOutput.
+ if (!line.empty() && line.find("<CTest") != std::string::npos) {
+ if (this->TestHandler->CustomCompletionStatusRegex.find(line)) {
+ this->TestResult.CustomCompletionStatus =
+ this->TestHandler->CustomCompletionStatusRegex.match(1);
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->GetIndex() << ": "
+ << "Test Details changed to '"
+ << this->TestResult.CustomCompletionStatus
+ << "'" << std::endl);
+ return;
+ }
+ }
+
this->ProcessOutput += line;
this->ProcessOutput += "\n";
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 4808c36aa..d2cad3992 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -4,7 +4,6 @@
#include <cstdio>
#include <cstdlib>
-#include <cstring>
#include <map>
#include <ratio>
#include <sstream>
@@ -91,7 +90,7 @@ void cmCTestScriptHandler::Initialize()
cmCTestScriptHandler::~cmCTestScriptHandler() = default;
// just adds an argument to the vector
-void cmCTestScriptHandler::AddConfigurationScript(const char* script,
+void cmCTestScriptHandler::AddConfigurationScript(const std::string& script,
bool pscope)
{
this->ConfigurationScripts.emplace_back(script);
@@ -676,7 +675,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
// clear the binary directory?
if (this->EmptyBinDir) {
- if (!cmCTestScriptHandler::EmptyBinaryDirectory(this->BinaryDir.c_str())) {
+ if (!cmCTestScriptHandler::EmptyBinaryDirectory(this->BinaryDir)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Problem removing the binary directory" << std::endl);
}
@@ -724,8 +723,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
// put the initial cache into the bin dir
if (!this->InitialCache.empty()) {
- if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir.c_str(),
- this->InitialCache.c_str())) {
+ if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir,
+ this->InitialCache)) {
this->RestoreBackupDirectories();
return 9;
}
@@ -812,8 +811,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
return 0;
}
-bool cmCTestScriptHandler::WriteInitialCache(const char* directory,
- const char* text)
+bool cmCTestScriptHandler::WriteInitialCache(const std::string& directory,
+ const std::string& text)
{
std::string cacheFile = cmStrCat(directory, "/CMakeCache.txt");
cmGeneratedFileStream fout(cacheFile);
@@ -821,9 +820,7 @@ bool cmCTestScriptHandler::WriteInitialCache(const char* directory,
return false;
}
- if (text != nullptr) {
- fout.write(text, strlen(text));
- }
+ fout.write(text.data(), text.size());
// Make sure the operating system has finished writing the file
// before closing it. This will ensure the file is finished before
@@ -852,7 +849,7 @@ void cmCTestScriptHandler::RestoreBackupDirectories()
}
bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf,
- const char* sname, bool InProcess,
+ const std::string& sname, bool InProcess,
int* returnValue)
{
auto sh = cm::make_unique<cmCTestScriptHandler>();
@@ -866,10 +863,10 @@ bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf,
return true;
}
-bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname)
+bool cmCTestScriptHandler::EmptyBinaryDirectory(const std::string& sname)
{
// try to avoid deleting root
- if (!sname || strlen(sname) < 2) {
+ if (sname.size() < 2) {
return false;
}
@@ -924,7 +921,7 @@ bool cmCTestScriptHandler::TryToRemoveBinaryDirectoryOnce(
}
}
- return cmSystemTools::RemoveADirectory(directoryPath);
+ return static_cast<bool>(cmSystemTools::RemoveADirectory(directoryPath));
}
cmDuration cmCTestScriptHandler::GetRemainingTimeAllowed()
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index 8eb96582b..b7764b2a7 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -62,7 +62,7 @@ public:
/**
* Add a script to run, and if is should run in the current process
*/
- void AddConfigurationScript(const char*, bool pscope);
+ void AddConfigurationScript(const std::string&, bool pscope);
/**
* Run a dashboard using a specified confiuration script
@@ -72,19 +72,21 @@ public:
/*
* Run a script
*/
- static bool RunScript(cmCTest* ctest, cmMakefile* mf, const char* script,
- bool InProcess, int* returnValue);
+ static bool RunScript(cmCTest* ctest, cmMakefile* mf,
+ const std::string& script, bool InProcess,
+ int* returnValue);
int RunCurrentScript();
/*
* Empty Binary Directory
*/
- static bool EmptyBinaryDirectory(const char* dir);
+ static bool EmptyBinaryDirectory(const std::string& dir);
/*
* Write an initial CMakeCache.txt from the given contents.
*/
- static bool WriteInitialCache(const char* directory, const char* text);
+ static bool WriteInitialCache(const std::string& directory,
+ const std::string& text);
/*
* Some elapsed time handling functions
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 440373373..67f498608 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -9,7 +9,6 @@
#include <cmext/string_view>
#include "cmCTest.h"
-#include "cmCTestGenericHandler.h"
#include "cmCTestTestHandler.h"
#include "cmDuration.h"
#include "cmMakefile.h"
@@ -36,6 +35,7 @@ void cmCTestTestCommand::BindArguments()
this->Bind("TEST_LOAD"_s, this->TestLoad);
this->Bind("RESOURCE_SPEC_FILE"_s, this->ResourceSpecFile);
this->Bind("STOP_ON_FAILURE"_s, this->StopOnFailure);
+ this->Bind("OUTPUT_JUNIT"_s, this->OutputJUnit);
}
cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
@@ -60,7 +60,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
this->ResourceSpecFile = *resourceSpecFile;
}
- cmCTestGenericHandler* handler = this->InitializeActualHandler();
+ cmCTestTestHandler* handler = this->InitializeActualHandler();
if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) {
handler->SetOption(
"TestsToRunInformation",
@@ -73,11 +73,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
handler->SetOption("IncludeRegularExpression", this->Include.c_str());
}
if (!this->ExcludeLabel.empty()) {
- handler->SetOption("ExcludeLabelRegularExpression",
- this->ExcludeLabel.c_str());
+ handler->AddMultiOption("ExcludeLabelRegularExpression",
+ this->ExcludeLabel);
}
if (!this->IncludeLabel.empty()) {
- handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str());
+ handler->AddMultiOption("LabelRegularExpression", this->IncludeLabel);
}
if (!this->ExcludeFixture.empty()) {
handler->SetOption("ExcludeFixtureRegularExpression",
@@ -140,11 +140,15 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
*labelsForSubprojects, this->Quiet);
}
+ if (!this->OutputJUnit.empty()) {
+ handler->SetJUnitXMLFileName(this->OutputJUnit);
+ }
+
handler->SetQuiet(this->Quiet);
return handler;
}
-cmCTestGenericHandler* cmCTestTestCommand::InitializeActualHandler()
+cmCTestTestHandler* cmCTestTestCommand::InitializeActualHandler()
{
cmCTestTestHandler* handler = this->CTest->GetTestHandler();
handler->Initialize();
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index 624cd91fe..24e74e2ba 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -13,6 +13,7 @@
#include "cmCommand.h"
class cmCTestGenericHandler;
+class cmCTestTestHandler;
/** \class cmCTestTest
* \brief Run a ctest script
@@ -40,7 +41,7 @@ public:
protected:
void BindArguments() override;
- virtual cmCTestGenericHandler* InitializeActualHandler();
+ virtual cmCTestTestHandler* InitializeActualHandler();
cmCTestGenericHandler* InitializeHandler() override;
std::string Start;
@@ -59,5 +60,6 @@ protected:
std::string StopTime;
std::string TestLoad;
std::string ResourceSpecFile;
+ std::string OutputJUnit;
bool StopOnFailure = false;
};
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 1cb5d0090..730ec0f04 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -42,6 +42,7 @@
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTimestamp.h"
#include "cmWorkingDirectory.h"
#include "cmXMLWriter.h"
#include "cmake.h"
@@ -287,8 +288,6 @@ cmCTestTestHandler::cmCTestTestHandler()
{
this->UseUnion = false;
- this->UseIncludeLabelRegExpFlag = false;
- this->UseExcludeLabelRegExpFlag = false;
this->UseIncludeRegExpFlag = false;
this->UseExcludeRegExpFlag = false;
this->UseExcludeRegExpFirst = false;
@@ -301,11 +300,18 @@ cmCTestTestHandler::cmCTestTestHandler()
this->LogFile = nullptr;
+ // Support for JUnit XML output.
+ this->JUnitXMLFileName = "";
+
// regex to detect <DartMeasurement>...</DartMeasurement>
this->DartStuff.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
// regex to detect each individual <DartMeasurement>...</DartMeasurement>
this->DartStuff1.compile(
"(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)");
+
+ // regex to detect <CTestDetails>...</CTestDetails>
+ this->CustomCompletionStatusRegex.compile(
+ "<CTestDetails>(.*)</CTestDetails>");
}
void cmCTestTestHandler::Initialize()
@@ -327,13 +333,11 @@ void cmCTestTestHandler::Initialize()
this->TestsToRun.clear();
- this->UseIncludeLabelRegExpFlag = false;
- this->UseExcludeLabelRegExpFlag = false;
this->UseIncludeRegExpFlag = false;
this->UseExcludeRegExpFlag = false;
this->UseExcludeRegExpFirst = false;
- this->IncludeLabelRegularExpression = "";
- this->ExcludeLabelRegularExpression = "";
+ this->IncludeLabelRegularExpressions.clear();
+ this->ExcludeLabelRegularExpressions.clear();
this->IncludeRegExp.clear();
this->ExcludeRegExp.clear();
this->ExcludeFixtureRegExp.clear();
@@ -460,6 +464,10 @@ int cmCTestTestHandler::ProcessHandler()
return 1;
}
+ if (!this->WriteJUnitXML()) {
+ return 1;
+ }
+
if (!this->PostProcessHandler()) {
this->LogFile = nullptr;
return -1;
@@ -479,6 +487,22 @@ int cmCTestTestHandler::ProcessHandler()
return 0;
}
+/* Given a multi-option value `parts`, compile those parts into
+ * regular expressions in `expressions`. Skip empty values.
+ * Returns true if there were any expressions.
+ */
+static bool BuildLabelRE(const std::vector<std::string>& parts,
+ std::vector<cmsys::RegularExpression>& expressions)
+{
+ expressions.clear();
+ for (const auto& p : parts) {
+ if (!p.empty()) {
+ expressions.emplace_back(p);
+ }
+ }
+ return !expressions.empty();
+}
+
bool cmCTestTestHandler::ProcessOptions()
{
// Update internal data structure from generic one
@@ -519,18 +543,11 @@ bool cmCTestTestHandler::ProcessOptions()
this->CTest->SetStopOnFailure(true);
}
- const char* val;
- val = this->GetOption("LabelRegularExpression");
- if (val) {
- this->UseIncludeLabelRegExpFlag = true;
- this->IncludeLabelRegExp = val;
- }
- val = this->GetOption("ExcludeLabelRegularExpression");
- if (val) {
- this->UseExcludeLabelRegExpFlag = true;
- this->ExcludeLabelRegExp = val;
- }
- val = this->GetOption("IncludeRegularExpression");
+ BuildLabelRE(this->GetMultiOption("LabelRegularExpression"),
+ this->IncludeLabelRegularExpressions);
+ BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"),
+ this->ExcludeLabelRegularExpressions);
+ const char* val = this->GetOption("IncludeRegularExpression");
if (val) {
this->UseIncludeRegExp();
this->SetIncludeRegExp(val);
@@ -763,10 +780,40 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject)
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
}
+/**
+ * Check if the labels (from a test) match all the expressions.
+ *
+ * Each of the RE's must match at least one label
+ * (e.g. all of the REs must match **some** label,
+ * in order for the filter to apply to the test).
+ */
+static bool MatchLabelsAgainstFilterRE(
+ const std::vector<std::string>& labels,
+ const std::vector<cmsys::RegularExpression>& expressions)
+{
+ for (const auto& re : expressions) {
+ // check to see if the label regular expression matches
+ bool found = false; // assume it does not match
+ cmsys::RegularExpressionMatch match;
+ // loop over all labels and look for match
+ for (std::string const& l : labels) {
+ if (re.find(l.c_str(), match)) {
+ found = true;
+ break;
+ }
+ }
+ // if no match was found, exclude the test
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+}
+
void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
{
// if not using Labels to filter then return
- if (!this->UseIncludeLabelRegExpFlag) {
+ if (this->IncludeLabelRegularExpressions.empty()) {
return;
}
// if there are no labels and we are filtering by labels
@@ -775,16 +822,9 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
it.IsInBasedOnREOptions = false;
return;
}
- // check to see if the label regular expression matches
- bool found = false; // assume it does not match
- // loop over all labels and look for match
- for (std::string const& l : it.Labels) {
- if (this->IncludeLabelRegularExpression.find(l)) {
- found = true;
- }
- }
// if no match was found, exclude the test
- if (!found) {
+ if (!MatchLabelsAgainstFilterRE(it.Labels,
+ this->IncludeLabelRegularExpressions)) {
it.IsInBasedOnREOptions = false;
}
}
@@ -792,7 +832,7 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it)
{
// if not using Labels to filter then return
- if (!this->UseExcludeLabelRegExpFlag) {
+ if (this->ExcludeLabelRegularExpressions.empty()) {
return;
}
// if there are no labels and we are excluding by labels
@@ -800,16 +840,9 @@ void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it)
if (it.Labels.empty()) {
return;
}
- // check to see if the label regular expression matches
- bool found = false; // assume it does not match
- // loop over all labels and look for match
- for (std::string const& l : it.Labels) {
- if (this->ExcludeLabelRegularExpression.find(l)) {
- found = true;
- }
- }
// if match was found, exclude the test
- if (found) {
+ if (MatchLabelsAgainstFilterRE(it.Labels,
+ this->ExcludeLabelRegularExpressions)) {
it.IsInBasedOnREOptions = false;
}
}
@@ -1431,7 +1464,11 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Completion Status");
- xml.Element("Value", result.CompletionStatus);
+ if (result.CustomCompletionStatus.empty()) {
+ xml.Element("Value", result.CompletionStatus);
+ } else {
+ xml.Element("Value", result.CustomCompletionStatus);
+ }
xml.EndElement(); // NamedMeasurement
xml.StartElement("NamedMeasurement");
@@ -1521,19 +1558,29 @@ void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml,
result.Properties->AttachOnFail.end());
}
for (std::string const& file : result.Properties->AttachedFiles) {
- const std::string& base64 = this->CTest->Base64GzipEncodeFile(file);
- std::string const fname = cmSystemTools::GetFilenameName(file);
- xml.StartElement("NamedMeasurement");
- xml.Attribute("name", "Attached File");
- xml.Attribute("encoding", "base64");
- xml.Attribute("compression", "tar/gzip");
- xml.Attribute("filename", fname);
- xml.Attribute("type", "file");
- xml.Element("Value", base64);
- xml.EndElement(); // NamedMeasurement
+ this->AttachFile(xml, file, "");
}
}
+void cmCTestTestHandler::AttachFile(cmXMLWriter& xml, std::string const& file,
+ std::string const& name)
+{
+ const std::string& base64 = this->CTest->Base64GzipEncodeFile(file);
+ std::string const fname = cmSystemTools::GetFilenameName(file);
+ xml.StartElement("NamedMeasurement");
+ std::string measurement_name = name;
+ if (measurement_name.empty()) {
+ measurement_name = "Attached File";
+ }
+ xml.Attribute("name", measurement_name);
+ xml.Attribute("encoding", "base64");
+ xml.Attribute("compression", "tar/gzip");
+ xml.Attribute("filename", fname);
+ xml.Attribute("type", "file");
+ xml.Element("Value", base64);
+ xml.EndElement(); // NamedMeasurement
+}
+
int cmCTestTestHandler::ExecuteCommands(std::vector<std::string>& vec)
{
for (std::string const& it : vec) {
@@ -1704,19 +1751,11 @@ bool cmCTestTestHandler::ParseResourceGroupsProperty(
bool cmCTestTestHandler::GetListOfTests()
{
- if (!this->IncludeLabelRegExp.empty()) {
- this->IncludeLabelRegularExpression.compile(
- this->IncludeLabelRegExp.c_str());
- }
- if (!this->ExcludeLabelRegExp.empty()) {
- this->ExcludeLabelRegularExpression.compile(
- this->ExcludeLabelRegExp.c_str());
- }
if (!this->IncludeRegExp.empty()) {
- this->IncludeTestsRegularExpression.compile(this->IncludeRegExp.c_str());
+ this->IncludeTestsRegularExpression.compile(this->IncludeRegExp);
}
if (!this->ExcludeRegExp.empty()) {
- this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp.c_str());
+ this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp);
}
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Constructing a list of tests" << std::endl, this->Quiet);
@@ -1868,7 +1907,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
std::string dirName = this->CTest->GetBinaryDir() + "/Testing/Temporary";
cmsys::Directory directory;
- if (directory.Load(dirName) == 0) {
+ if (!directory.Load(dirName)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Unable to read the contents of " << dirName << std::endl);
return;
@@ -2020,11 +2059,11 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
cmCTest::CleanString(measurementfile.match(5));
if (cmSystemTools::FileExists(filename)) {
long len = cmSystemTools::FileLength(filename);
+ std::string k1 = measurementfile.match(1);
+ std::string v1 = measurementfile.match(2);
+ std::string k2 = measurementfile.match(3);
+ std::string v2 = measurementfile.match(4);
if (len == 0) {
- std::string k1 = measurementfile.match(1);
- std::string v1 = measurementfile.match(2);
- std::string k2 = measurementfile.match(3);
- std::string v2 = measurementfile.match(4);
if (cmSystemTools::LowerCase(k1) == "type") {
v1 = "text/string";
}
@@ -2039,35 +2078,53 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
xml.Element("Value", "Image " + filename + " is empty");
xml.EndElement();
} else {
- cmsys::ifstream ifs(filename.c_str(),
- std::ios::in
+ std::string type;
+ std::string name;
+ if (cmSystemTools::LowerCase(k1) == "type") {
+ type = v1;
+ } else if (cmSystemTools::LowerCase(k2) == "type") {
+ type = v2;
+ }
+ if (cmSystemTools::LowerCase(k1) == "name") {
+ name = v1;
+ } else if (cmSystemTools::LowerCase(k2) == "name") {
+ name = v2;
+ }
+ if (type == "file") {
+ // Treat this measurement like an "ATTACHED_FILE" when the type
+ // is explicitly "file" (not an image).
+ this->AttachFile(xml, filename, name);
+ } else {
+ cmsys::ifstream ifs(filename.c_str(),
+ std::ios::in
#ifdef _WIN32
- | std::ios::binary
+ | std::ios::binary
#endif
- );
- auto file_buffer = cm::make_unique<unsigned char[]>(len + 1);
- ifs.read(reinterpret_cast<char*>(file_buffer.get()), len);
- auto encoded_buffer = cm::make_unique<unsigned char[]>(
- static_cast<int>(static_cast<double>(len) * 1.5 + 5.0));
-
- size_t rlen = cmsysBase64_Encode(file_buffer.get(), len,
- encoded_buffer.get(), 1);
-
- xml.StartElement("NamedMeasurement");
- xml.Attribute(measurementfile.match(1).c_str(),
- measurementfile.match(2));
- xml.Attribute(measurementfile.match(3).c_str(),
- measurementfile.match(4));
- xml.Attribute("encoding", "base64");
- std::ostringstream ostr;
- for (size_t cc = 0; cc < rlen; cc++) {
- ostr << encoded_buffer[cc];
- if (cc % 60 == 0 && cc) {
- ostr << std::endl;
+ );
+ auto file_buffer = cm::make_unique<unsigned char[]>(len + 1);
+ ifs.read(reinterpret_cast<char*>(file_buffer.get()), len);
+ auto encoded_buffer = cm::make_unique<unsigned char[]>(
+ static_cast<int>(static_cast<double>(len) * 1.5 + 5.0));
+
+ size_t rlen = cmsysBase64_Encode(file_buffer.get(), len,
+ encoded_buffer.get(), 1);
+
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(measurementfile.match(1).c_str(),
+ measurementfile.match(2));
+ xml.Attribute(measurementfile.match(3).c_str(),
+ measurementfile.match(4));
+ xml.Attribute("encoding", "base64");
+ std::ostringstream ostr;
+ for (size_t cc = 0; cc < rlen; cc++) {
+ ostr << encoded_buffer[cc];
+ if (cc % 60 == 0 && cc) {
+ ostr << std::endl;
+ }
}
+ xml.Element("Value", ostr.str());
+ xml.EndElement(); // NamedMeasurement
}
- xml.Element("Value", ostr.str());
- xml.EndElement(); // NamedMeasurement
}
} else {
int idx = 4;
@@ -2444,3 +2501,125 @@ bool cmCTestTestHandler::cmCTestTestResourceRequirement::operator!=(
{
return !(*this == other);
}
+
+void cmCTestTestHandler::SetJUnitXMLFileName(const std::string& filename)
+{
+ this->JUnitXMLFileName = filename;
+}
+
+bool cmCTestTestHandler::WriteJUnitXML()
+{
+ if (this->JUnitXMLFileName.empty()) {
+ return true;
+ }
+
+ // Open new XML file for writing.
+ cmGeneratedFileStream xmlfile;
+ xmlfile.SetTempExt("tmp");
+ xmlfile.Open(this->JUnitXMLFileName);
+ if (!xmlfile) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Problem opening file: " << this->JUnitXMLFileName
+ << std::endl);
+ return false;
+ }
+ cmXMLWriter xml(xmlfile);
+
+ // Iterate over the test results to get the number of tests that
+ // passed, failed, etc.
+ auto num_tests = 0;
+ auto num_passed = 0;
+ auto num_failed = 0;
+ auto num_notrun = 0;
+ auto num_disabled = 0;
+ SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end());
+ for (cmCTestTestResult const& result : resultsSet) {
+ num_tests++;
+ if (result.Status == cmCTestTestHandler::COMPLETED) {
+ num_passed++;
+ } else if (result.Status == cmCTestTestHandler::NOT_RUN) {
+ if (result.CompletionStatus == "Disabled") {
+ num_disabled++;
+ } else {
+ num_notrun++;
+ }
+ } else {
+ num_failed++;
+ }
+ }
+
+ // Write <testsuite> element.
+ xml.StartDocument();
+ xml.StartElement("testsuite");
+
+ xml.Attribute("name",
+ cmCTest::SafeBuildIdField(
+ this->CTest->GetCTestConfiguration("BuildName")));
+ xml.BreakAttributes();
+
+ xml.Attribute("tests", num_tests);
+ xml.Attribute("failures", num_failed);
+
+ // CTest disabled => JUnit disabled
+ xml.Attribute("disabled", num_disabled);
+
+ // Otherwise, CTest notrun => JUnit skipped.
+ // The distinction between JUnit disabled vs. skipped is that
+ // skipped tests can have a message associated with them
+ // (why the test was skipped).
+ xml.Attribute("skipped", num_notrun);
+
+ xml.Attribute("hostname", this->CTest->GetCTestConfiguration("Site"));
+ xml.Attribute(
+ "time",
+ std::chrono::duration_cast<std::chrono::seconds>(this->ElapsedTestingTime)
+ .count());
+ const std::time_t start_test_time_t =
+ std::chrono::system_clock::to_time_t(this->StartTestTime);
+ cmTimestamp cmts;
+ xml.Attribute("timestamp",
+ cmts.CreateTimestampFromTimeT(start_test_time_t,
+ "%Y-%m-%dT%H:%M:%S", false));
+
+ // Write <testcase> elements.
+ for (cmCTestTestResult const& result : resultsSet) {
+ xml.StartElement("testcase");
+ xml.Attribute("name", result.Name);
+ xml.Attribute("classname", result.Name);
+ xml.Attribute("time", result.ExecutionTime.count());
+
+ std::string status;
+ if (result.Status == cmCTestTestHandler::COMPLETED) {
+ status = "run";
+ } else if (result.Status == cmCTestTestHandler::NOT_RUN) {
+ if (result.CompletionStatus == "Disabled") {
+ status = "disabled";
+ } else {
+ status = "notrun";
+ }
+ } else {
+ status = "fail";
+ }
+ xml.Attribute("status", status);
+
+ if (status == "notrun") {
+ xml.StartElement("skipped");
+ xml.Attribute("message", result.CompletionStatus);
+ xml.EndElement(); // </skipped>
+ } else if (status == "fail") {
+ xml.StartElement("failure");
+ xml.Attribute("message", result.Reason);
+ xml.EndElement(); // </failure>
+ }
+
+ // Note: compressed test output is unconditionally disabled when
+ // --output-junit is specified.
+ xml.Element("system-out", result.Output);
+ xml.EndElement(); // </testcase>
+ }
+
+ xml.EndElement(); // </testsuite>
+ xml.EndDocument();
+
+ return true;
+}
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index aa29eeb01..bd51738b8 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -175,6 +175,7 @@ public:
std::string ExceptionStatus;
bool CompressOutput;
std::string CompletionStatus;
+ std::string CustomCompletionStatus;
std::string Output;
std::string DartString;
int TestCount;
@@ -209,6 +210,9 @@ public:
using ListOfTests = std::vector<cmCTestTestProperties>;
+ // Support for writing test results in JUnit XML format.
+ void SetJUnitXMLFileName(const std::string& id);
+
protected:
using SetOfTests =
std::set<cmCTestTestHandler::cmCTestTestResult, cmCTestTestResultLess>;
@@ -234,6 +238,8 @@ protected:
cmCTestTestResult const& result);
// Write attached test files into the xml
void AttachFiles(cmXMLWriter& xml, cmCTestTestResult& result);
+ void AttachFile(cmXMLWriter& xml, std::string const& file,
+ std::string const& name);
//! Clean test output to specified length
void CleanTestOutput(std::string& output, size_t length);
@@ -274,6 +280,11 @@ private:
*/
virtual void GenerateDartOutput(cmXMLWriter& xml);
+ /**
+ * Write test results in JUnit XML format
+ */
+ bool WriteJUnitXML();
+
void PrintLabelOrSubprojectSummary(bool isSubProject);
/**
@@ -320,20 +331,16 @@ private:
std::vector<int> TestsToRun;
- bool UseIncludeLabelRegExpFlag;
- bool UseExcludeLabelRegExpFlag;
bool UseIncludeRegExpFlag;
bool UseExcludeRegExpFlag;
bool UseExcludeRegExpFirst;
- std::string IncludeLabelRegExp;
- std::string ExcludeLabelRegExp;
std::string IncludeRegExp;
std::string ExcludeRegExp;
std::string ExcludeFixtureRegExp;
std::string ExcludeFixtureSetupRegExp;
std::string ExcludeFixtureCleanupRegExp;
- cmsys::RegularExpression IncludeLabelRegularExpression;
- cmsys::RegularExpression ExcludeLabelRegularExpression;
+ std::vector<cmsys::RegularExpression> IncludeLabelRegularExpressions;
+ std::vector<cmsys::RegularExpression> ExcludeLabelRegularExpressions;
cmsys::RegularExpression IncludeTestsRegularExpression;
cmsys::RegularExpression ExcludeTestsRegularExpression;
@@ -352,10 +359,13 @@ private:
ListOfTests TestList;
size_t TotalNumberOfTests;
cmsys::RegularExpression DartStuff;
+ cmsys::RegularExpression CustomCompletionStatusRegex;
std::ostream* LogFile;
cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never;
int RepeatCount = 1;
bool RerunFailed;
+
+ std::string JUnitXMLFileName;
};
diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx
index 0ba2c417b..797cb014e 100644
--- a/Source/CTest/cmCTestUpdateCommand.cxx
+++ b/Source/CTest/cmCTestUpdateCommand.cxx
@@ -75,7 +75,6 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
cmCTestUpdateHandler* handler = this->CTest->GetUpdateHandler();
handler->Initialize();
- handler->SetCommand(this);
if (source_dir.empty()) {
this->SetError("source directory not specified. Please use SOURCE tag");
return nullptr;
diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake
index 7917d41fa..f20572e06 100644
--- a/Source/Checks/cm_cxx_features.cmake
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -80,7 +80,9 @@ if(CMake_HAVE_CXX_MAKE_UNIQUE)
set(CMake_HAVE_CXX_UNIQUE_PTR 1)
endif()
cm_check_cxx_feature(unique_ptr)
-if (NOT CMAKE_CXX_STANDARD LESS "17")
+if (NOT CMAKE_CXX_STANDARD LESS "17"
+ AND NOT MSYS # FIXME: RunCMake.cmake_path cases crash with MSYS std::filesystem
+ )
if (NOT CMAKE_CROSSCOMPILING OR CMAKE_CROSSCOMPILING_EMULATOR)
cm_check_cxx_feature(filesystem TRY_RUN)
else()
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 85e256b8b..1ba45e5f7 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -19,6 +19,7 @@
#include "cmCursesStandardIncludes.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h" // IWYU pragma: keep
+#include "cmMessageMetadata.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -181,8 +182,8 @@ int main(int argc, char const* const* argv)
return msg;
};
cmSystemTools::SetMessageCallback(
- [&](const std::string& message, const char* title) {
- myform->AddError(cleanMessage(message), title);
+ [&](const std::string& message, const cmMessageMetadata& md) {
+ myform->AddError(cleanMessage(message), md.title);
});
cmSystemTools::SetStderrCallback([&](const std::string& message) {
myform->AddError(cleanMessage(message), "");
diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt
index 8f26b9aaa..9202bc12e 100644
--- a/Source/CursesDialog/form/CMakeLists.txt
+++ b/Source/CursesDialog/form/CMakeLists.txt
@@ -5,7 +5,7 @@ project(CMAKE_FORM)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Source/LexerParser/cmCTestResourceGroupsLexer.cxx b/Source/LexerParser/cmCTestResourceGroupsLexer.cxx
index de07c4693..85b379bbe 100644
--- a/Source/LexerParser/cmCTestResourceGroupsLexer.cxx
+++ b/Source/LexerParser/cmCTestResourceGroupsLexer.cxx
@@ -659,7 +659,7 @@ Modify cmCTestResourceGroupsLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include "cmCTestResourceGroupsLexerHelper.h"
diff --git a/Source/LexerParser/cmCTestResourceGroupsLexer.in.l b/Source/LexerParser/cmCTestResourceGroupsLexer.in.l
index 2aabea48d..2befa85c8 100644
--- a/Source/LexerParser/cmCTestResourceGroupsLexer.in.l
+++ b/Source/LexerParser/cmCTestResourceGroupsLexer.in.l
@@ -18,7 +18,7 @@ Modify cmCTestResourceGroupsLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include "cmCTestResourceGroupsLexerHelper.h"
diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx
index 46220ffc7..4b7eb7981 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.cxx
+++ b/Source/LexerParser/cmCommandArgumentLexer.cxx
@@ -664,7 +664,7 @@ Modify cmCommandArgumentLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include "cmCommandArgumentParserHelper.h"
diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l
index 8ad23351a..6b4f9a966 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.in.l
+++ b/Source/LexerParser/cmCommandArgumentLexer.in.l
@@ -18,7 +18,7 @@ Modify cmCommandArgumentLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include "cmCommandArgumentParserHelper.h"
diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx
index b8bc82cd7..5727992aa 100644
--- a/Source/LexerParser/cmCommandArgumentParser.cxx
+++ b/Source/LexerParser/cmCommandArgumentParser.cxx
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.4. */
+/* A Bison parser, made by GNU Bison 3.7.5. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -46,10 +46,10 @@
USER NAME SPACE" below. */
/* Identify Bison output, and Bison version. */
-#define YYBISON 30704
+#define YYBISON 30705
/* Bison version string. */
-#define YYBISON_VERSION "3.7.4"
+#define YYBISON_VERSION "3.7.5"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -228,6 +228,18 @@ typedef int_least16_t yytype_int16;
typedef short yytype_int16;
#endif
+/* Work around bug in HP-UX 11.23, which defines these macros
+ incorrectly for preprocessor constants. This workaround can likely
+ be removed in 2023, as HPE has promised support for HP-UX 11.23
+ (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
+ <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */
+#ifdef __hpux
+# undef UINT_LEAST8_MAX
+# undef UINT_LEAST16_MAX
+# define UINT_LEAST8_MAX 255
+# define UINT_LEAST16_MAX 65535
+#endif
+
#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
@@ -325,9 +337,9 @@ typedef int yy_state_fast_t;
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
+# define YY_USE(E) ((void) (E))
#else
-# define YYUSE(E) /* empty */
+# define YY_USE(E) /* empty */
#endif
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
@@ -635,7 +647,7 @@ static const yytype_int8 yypgoto[] =
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 11, 12, 13, 14, 15, 19, 20, 21, 22
+ 0, 11, 12, 13, 14, 15, 19, 20, 21, 22
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
@@ -761,8 +773,8 @@ yy_symbol_value_print (FILE *yyo,
yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
FILE *yyoutput = yyo;
- YYUSE (yyoutput);
- YYUSE (yyscanner);
+ YY_USE (yyoutput);
+ YY_USE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
@@ -770,7 +782,7 @@ yy_symbol_value_print (FILE *yyo,
YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yykind);
+ YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -1151,14 +1163,14 @@ static void
yydestruct (const char *yymsg,
yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
- YYUSE (yyvaluep);
- YYUSE (yyscanner);
+ YY_USE (yyvaluep);
+ YY_USE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yykind);
+ YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -1433,7 +1445,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetResult((yyvsp[0].str));
}
-#line 1437 "cmCommandArgumentParser.cxx"
+#line 1449 "cmCommandArgumentParser.cxx"
break;
case 3: /* GoalWithOptionalBackSlash: Goal */
@@ -1441,7 +1453,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1445 "cmCommandArgumentParser.cxx"
+#line 1457 "cmCommandArgumentParser.cxx"
break;
case 4: /* GoalWithOptionalBackSlash: Goal "\\" */
@@ -1449,7 +1461,7 @@ yyreduce:
{
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1453 "cmCommandArgumentParser.cxx"
+#line 1465 "cmCommandArgumentParser.cxx"
break;
case 5: /* Goal: %empty */
@@ -1457,7 +1469,7 @@ yyreduce:
{
(yyval.str) = 0;
}
-#line 1461 "cmCommandArgumentParser.cxx"
+#line 1473 "cmCommandArgumentParser.cxx"
break;
case 6: /* Goal: String Goal */
@@ -1465,7 +1477,7 @@ yyreduce:
{
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1469 "cmCommandArgumentParser.cxx"
+#line 1481 "cmCommandArgumentParser.cxx"
break;
case 7: /* String: OuterText */
@@ -1473,7 +1485,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1477 "cmCommandArgumentParser.cxx"
+#line 1489 "cmCommandArgumentParser.cxx"
break;
case 8: /* String: Variable */
@@ -1481,7 +1493,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1485 "cmCommandArgumentParser.cxx"
+#line 1497 "cmCommandArgumentParser.cxx"
break;
case 9: /* OuterText: cal_NAME */
@@ -1489,7 +1501,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1493 "cmCommandArgumentParser.cxx"
+#line 1505 "cmCommandArgumentParser.cxx"
break;
case 10: /* OuterText: "@" */
@@ -1497,7 +1509,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1501 "cmCommandArgumentParser.cxx"
+#line 1513 "cmCommandArgumentParser.cxx"
break;
case 11: /* OuterText: "$" */
@@ -1505,7 +1517,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1509 "cmCommandArgumentParser.cxx"
+#line 1521 "cmCommandArgumentParser.cxx"
break;
case 12: /* OuterText: "{" */
@@ -1513,7 +1525,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1517 "cmCommandArgumentParser.cxx"
+#line 1529 "cmCommandArgumentParser.cxx"
break;
case 13: /* OuterText: "}" */
@@ -1521,7 +1533,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1525 "cmCommandArgumentParser.cxx"
+#line 1537 "cmCommandArgumentParser.cxx"
break;
case 14: /* OuterText: cal_SYMBOL */
@@ -1529,7 +1541,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1533 "cmCommandArgumentParser.cxx"
+#line 1545 "cmCommandArgumentParser.cxx"
break;
case 15: /* Variable: cal_ENVCURLY EnvVarName "}" */
@@ -1537,7 +1549,7 @@ yyreduce:
{
(yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
}
-#line 1541 "cmCommandArgumentParser.cxx"
+#line 1553 "cmCommandArgumentParser.cxx"
break;
case 16: /* Variable: cal_NCURLY MultipleIds "}" */
@@ -1545,7 +1557,7 @@ yyreduce:
{
(yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
}
-#line 1549 "cmCommandArgumentParser.cxx"
+#line 1561 "cmCommandArgumentParser.cxx"
break;
case 17: /* Variable: cal_DCURLY MultipleIds "}" */
@@ -1553,7 +1565,7 @@ yyreduce:
{
(yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str));
}
-#line 1557 "cmCommandArgumentParser.cxx"
+#line 1569 "cmCommandArgumentParser.cxx"
break;
case 18: /* Variable: cal_ATNAME */
@@ -1561,7 +1573,7 @@ yyreduce:
{
(yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str));
}
-#line 1565 "cmCommandArgumentParser.cxx"
+#line 1577 "cmCommandArgumentParser.cxx"
break;
case 19: /* EnvVarName: MultipleIds */
@@ -1569,7 +1581,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1573 "cmCommandArgumentParser.cxx"
+#line 1585 "cmCommandArgumentParser.cxx"
break;
case 20: /* EnvVarName: cal_SYMBOL EnvVarName */
@@ -1577,7 +1589,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[-1].str);
}
-#line 1581 "cmCommandArgumentParser.cxx"
+#line 1593 "cmCommandArgumentParser.cxx"
break;
case 21: /* MultipleIds: %empty */
@@ -1585,7 +1597,7 @@ yyreduce:
{
(yyval.str) = 0;
}
-#line 1589 "cmCommandArgumentParser.cxx"
+#line 1601 "cmCommandArgumentParser.cxx"
break;
case 22: /* MultipleIds: ID MultipleIds */
@@ -1593,7 +1605,7 @@ yyreduce:
{
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1597 "cmCommandArgumentParser.cxx"
+#line 1609 "cmCommandArgumentParser.cxx"
break;
case 23: /* ID: cal_NAME */
@@ -1601,7 +1613,7 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1605 "cmCommandArgumentParser.cxx"
+#line 1617 "cmCommandArgumentParser.cxx"
break;
case 24: /* ID: Variable */
@@ -1609,11 +1621,11 @@ yyreduce:
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1613 "cmCommandArgumentParser.cxx"
+#line 1625 "cmCommandArgumentParser.cxx"
break;
-#line 1617 "cmCommandArgumentParser.cxx"
+#line 1629 "cmCommandArgumentParser.cxx"
default: break;
}
diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h
index 578f7937c..414c6dd6b 100644
--- a/Source/LexerParser/cmCommandArgumentParserTokens.h
+++ b/Source/LexerParser/cmCommandArgumentParserTokens.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.4. */
+/* A Bison parser, made by GNU Bison 3.7.5. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/Source/LexerParser/cmDependsJavaLexer.cxx b/Source/LexerParser/cmDependsJavaLexer.cxx
index d703e3c95..bfe7e64f0 100644
--- a/Source/LexerParser/cmDependsJavaLexer.cxx
+++ b/Source/LexerParser/cmDependsJavaLexer.cxx
@@ -860,7 +860,7 @@ Modify cmDependsJavaLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include <iostream>
diff --git a/Source/LexerParser/cmDependsJavaLexer.in.l b/Source/LexerParser/cmDependsJavaLexer.in.l
index 3dd3c224a..942e0075f 100644
--- a/Source/LexerParser/cmDependsJavaLexer.in.l
+++ b/Source/LexerParser/cmDependsJavaLexer.in.l
@@ -18,7 +18,7 @@ Modify cmDependsJavaLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include <iostream>
diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx
index 27cc177e6..e6b3a7ee2 100644
--- a/Source/LexerParser/cmDependsJavaParser.cxx
+++ b/Source/LexerParser/cmDependsJavaParser.cxx
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.4. */
+/* A Bison parser, made by GNU Bison 3.7.5. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -46,10 +46,10 @@
USER NAME SPACE" below. */
/* Identify Bison output, and Bison version. */
-#define YYBISON 30704
+#define YYBISON 30705
/* Bison version string. */
-#define YYBISON_VERSION "3.7.4"
+#define YYBISON_VERSION "3.7.5"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -456,6 +456,18 @@ typedef int_least16_t yytype_int16;
typedef short yytype_int16;
#endif
+/* Work around bug in HP-UX 11.23, which defines these macros
+ incorrectly for preprocessor constants. This workaround can likely
+ be removed in 2023, as HPE has promised support for HP-UX 11.23
+ (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
+ <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */
+#ifdef __hpux
+# undef UINT_LEAST8_MAX
+# undef UINT_LEAST16_MAX
+# define UINT_LEAST8_MAX 255
+# define UINT_LEAST16_MAX 65535
+#endif
+
#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
@@ -553,9 +565,9 @@ typedef int yy_state_fast_t;
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
+# define YY_USE(E) ((void) (E))
#else
-# define YYUSE(E) /* empty */
+# define YY_USE(E) /* empty */
#endif
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
@@ -1108,7 +1120,7 @@ static const yytype_int16 yypgoto[] =
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 2, 156, 157, 158, 229, 112, 113, 75, 78,
+ 0, 2, 156, 157, 158, 229, 112, 113, 75, 78,
230, 231, 19, 20, 21, 22, 3, 4, 24, 30,
5, 31, 32, 33, 51, 52, 53, 54, 163, 164,
65, 66, 79, 67, 80, 96, 97, 98, 208, 209,
@@ -1803,8 +1815,8 @@ yy_symbol_value_print (FILE *yyo,
yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
FILE *yyoutput = yyo;
- YYUSE (yyoutput);
- YYUSE (yyscanner);
+ YY_USE (yyoutput);
+ YY_USE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
@@ -1812,7 +1824,7 @@ yy_symbol_value_print (FILE *yyo,
YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yykind);
+ YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -2193,14 +2205,14 @@ static void
yydestruct (const char *yymsg,
yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
- YYUSE (yyvaluep);
- YYUSE (yyscanner);
+ YY_USE (yyvaluep);
+ YY_USE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yykind);
+ YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -2477,7 +2489,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2481 "cmDependsJavaParser.cxx"
+#line 2493 "cmDependsJavaParser.cxx"
break;
case 3: /* Literal: IntegerLiteral */
@@ -2488,7 +2500,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2492 "cmDependsJavaParser.cxx"
+#line 2504 "cmDependsJavaParser.cxx"
break;
case 4: /* Literal: jp_FLOATINGPOINTLITERAL */
@@ -2499,7 +2511,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2503 "cmDependsJavaParser.cxx"
+#line 2515 "cmDependsJavaParser.cxx"
break;
case 5: /* Literal: jp_BOOLEANLITERAL */
@@ -2510,7 +2522,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2514 "cmDependsJavaParser.cxx"
+#line 2526 "cmDependsJavaParser.cxx"
break;
case 6: /* Literal: jp_CHARACTERLITERAL */
@@ -2521,7 +2533,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2525 "cmDependsJavaParser.cxx"
+#line 2537 "cmDependsJavaParser.cxx"
break;
case 7: /* Literal: jp_STRINGLITERAL */
@@ -2532,7 +2544,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2536 "cmDependsJavaParser.cxx"
+#line 2548 "cmDependsJavaParser.cxx"
break;
case 8: /* Literal: jp_NULLLITERAL */
@@ -2543,7 +2555,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2547 "cmDependsJavaParser.cxx"
+#line 2559 "cmDependsJavaParser.cxx"
break;
case 9: /* IntegerLiteral: jp_DECIMALINTEGERLITERAL */
@@ -2554,7 +2566,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2558 "cmDependsJavaParser.cxx"
+#line 2570 "cmDependsJavaParser.cxx"
break;
case 10: /* IntegerLiteral: jp_HEXINTEGERLITERAL */
@@ -2565,7 +2577,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2569 "cmDependsJavaParser.cxx"
+#line 2581 "cmDependsJavaParser.cxx"
break;
case 11: /* Type: PrimitiveType */
@@ -2576,7 +2588,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2580 "cmDependsJavaParser.cxx"
+#line 2592 "cmDependsJavaParser.cxx"
break;
case 12: /* Type: ReferenceType */
@@ -2587,7 +2599,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2591 "cmDependsJavaParser.cxx"
+#line 2603 "cmDependsJavaParser.cxx"
break;
case 13: /* PrimitiveType: jp_BYTE_TYPE */
@@ -2595,7 +2607,7 @@ yyreduce:
{
jpElementStart(0);
}
-#line 2599 "cmDependsJavaParser.cxx"
+#line 2611 "cmDependsJavaParser.cxx"
break;
case 14: /* PrimitiveType: jp_SHORT_TYPE */
@@ -2603,7 +2615,7 @@ yyreduce:
{
jpElementStart(0);
}
-#line 2607 "cmDependsJavaParser.cxx"
+#line 2619 "cmDependsJavaParser.cxx"
break;
case 15: /* PrimitiveType: jp_INT_TYPE */
@@ -2611,7 +2623,7 @@ yyreduce:
{
jpElementStart(0);
}
-#line 2615 "cmDependsJavaParser.cxx"
+#line 2627 "cmDependsJavaParser.cxx"
break;
case 16: /* PrimitiveType: jp_LONG_TYPE */
@@ -2619,7 +2631,7 @@ yyreduce:
{
jpElementStart(0);
}
-#line 2623 "cmDependsJavaParser.cxx"
+#line 2635 "cmDependsJavaParser.cxx"
break;
case 17: /* PrimitiveType: jp_CHAR_TYPE */
@@ -2627,7 +2639,7 @@ yyreduce:
{
jpElementStart(0);
}
-#line 2631 "cmDependsJavaParser.cxx"
+#line 2643 "cmDependsJavaParser.cxx"
break;
case 18: /* PrimitiveType: jp_FLOAT_TYPE */
@@ -2635,7 +2647,7 @@ yyreduce:
{
jpElementStart(0);
}
-#line 2639 "cmDependsJavaParser.cxx"
+#line 2651 "cmDependsJavaParser.cxx"
break;
case 19: /* PrimitiveType: jp_DOUBLE_TYPE */
@@ -2643,7 +2655,7 @@ yyreduce:
{
jpElementStart(0);
}
-#line 2647 "cmDependsJavaParser.cxx"
+#line 2659 "cmDependsJavaParser.cxx"
break;
case 20: /* PrimitiveType: jp_BOOLEAN_TYPE */
@@ -2651,7 +2663,7 @@ yyreduce:
{
jpElementStart(0);
}
-#line 2655 "cmDependsJavaParser.cxx"
+#line 2667 "cmDependsJavaParser.cxx"
break;
case 21: /* ReferenceType: ClassOrInterfaceType */
@@ -2662,7 +2674,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2666 "cmDependsJavaParser.cxx"
+#line 2678 "cmDependsJavaParser.cxx"
break;
case 22: /* ReferenceType: ArrayType */
@@ -2673,7 +2685,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2677 "cmDependsJavaParser.cxx"
+#line 2689 "cmDependsJavaParser.cxx"
break;
case 23: /* ClassOrInterfaceType: Name */
@@ -2685,7 +2697,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2689 "cmDependsJavaParser.cxx"
+#line 2701 "cmDependsJavaParser.cxx"
break;
case 24: /* ClassType: ClassOrInterfaceType */
@@ -2696,7 +2708,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2700 "cmDependsJavaParser.cxx"
+#line 2712 "cmDependsJavaParser.cxx"
break;
case 25: /* InterfaceType: ClassOrInterfaceType */
@@ -2707,7 +2719,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2711 "cmDependsJavaParser.cxx"
+#line 2723 "cmDependsJavaParser.cxx"
break;
case 26: /* ArrayType: PrimitiveType Dims */
@@ -2718,7 +2730,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2722 "cmDependsJavaParser.cxx"
+#line 2734 "cmDependsJavaParser.cxx"
break;
case 27: /* ArrayType: Name Dims */
@@ -2730,7 +2742,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2734 "cmDependsJavaParser.cxx"
+#line 2746 "cmDependsJavaParser.cxx"
break;
case 28: /* Name: SimpleName */
@@ -2739,7 +2751,7 @@ yyreduce:
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2743 "cmDependsJavaParser.cxx"
+#line 2755 "cmDependsJavaParser.cxx"
break;
case 29: /* Name: QualifiedName */
@@ -2748,7 +2760,7 @@ yyreduce:
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2752 "cmDependsJavaParser.cxx"
+#line 2764 "cmDependsJavaParser.cxx"
break;
case 30: /* SimpleName: Identifier */
@@ -2757,7 +2769,7 @@ yyreduce:
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2761 "cmDependsJavaParser.cxx"
+#line 2773 "cmDependsJavaParser.cxx"
break;
case 31: /* Identifier: jp_NAME */
@@ -2766,7 +2778,7 @@ yyreduce:
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2770 "cmDependsJavaParser.cxx"
+#line 2782 "cmDependsJavaParser.cxx"
break;
case 32: /* Identifier: jp_DOLLAR jp_NAME */
@@ -2775,7 +2787,7 @@ yyreduce:
jpElementStart(2);
(yyval.str) = (yyvsp[0].str);
}
-#line 2779 "cmDependsJavaParser.cxx"
+#line 2791 "cmDependsJavaParser.cxx"
break;
case 33: /* QualifiedName: Name jp_DOT Identifier */
@@ -2787,7 +2799,7 @@ yyreduce:
yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
(yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine());
}
-#line 2791 "cmDependsJavaParser.cxx"
+#line 2803 "cmDependsJavaParser.cxx"
break;
case 34: /* QualifiedName: Name jp_DOT jp_CLASS */
@@ -2800,7 +2812,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2804 "cmDependsJavaParser.cxx"
+#line 2816 "cmDependsJavaParser.cxx"
break;
case 35: /* QualifiedName: Name jp_DOT jp_THIS */
@@ -2813,7 +2825,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2817 "cmDependsJavaParser.cxx"
+#line 2829 "cmDependsJavaParser.cxx"
break;
case 36: /* QualifiedName: SimpleType jp_DOT jp_CLASS */
@@ -2824,7 +2836,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2828 "cmDependsJavaParser.cxx"
+#line 2840 "cmDependsJavaParser.cxx"
break;
case 37: /* SimpleType: PrimitiveType */
@@ -2835,7 +2847,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2839 "cmDependsJavaParser.cxx"
+#line 2851 "cmDependsJavaParser.cxx"
break;
case 38: /* SimpleType: jp_VOID */
@@ -2846,7 +2858,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2850 "cmDependsJavaParser.cxx"
+#line 2862 "cmDependsJavaParser.cxx"
break;
case 39: /* CompilationUnit: PackageDeclarationopt ImportDeclarations TypeDeclarations */
@@ -2857,7 +2869,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2861 "cmDependsJavaParser.cxx"
+#line 2873 "cmDependsJavaParser.cxx"
break;
case 40: /* PackageDeclarationopt: %empty */
@@ -2867,7 +2879,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2871 "cmDependsJavaParser.cxx"
+#line 2883 "cmDependsJavaParser.cxx"
break;
case 41: /* PackageDeclarationopt: PackageDeclaration */
@@ -2878,7 +2890,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2882 "cmDependsJavaParser.cxx"
+#line 2894 "cmDependsJavaParser.cxx"
break;
case 42: /* ImportDeclarations: %empty */
@@ -2888,7 +2900,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2892 "cmDependsJavaParser.cxx"
+#line 2904 "cmDependsJavaParser.cxx"
break;
case 43: /* ImportDeclarations: ImportDeclarations ImportDeclaration */
@@ -2899,7 +2911,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2903 "cmDependsJavaParser.cxx"
+#line 2915 "cmDependsJavaParser.cxx"
break;
case 44: /* TypeDeclarations: %empty */
@@ -2909,7 +2921,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2913 "cmDependsJavaParser.cxx"
+#line 2925 "cmDependsJavaParser.cxx"
break;
case 45: /* TypeDeclarations: TypeDeclarations TypeDeclaration */
@@ -2920,7 +2932,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2924 "cmDependsJavaParser.cxx"
+#line 2936 "cmDependsJavaParser.cxx"
break;
case 46: /* PackageDeclaration: jp_PACKAGE Name jp_SEMICOL */
@@ -2934,7 +2946,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2938 "cmDependsJavaParser.cxx"
+#line 2950 "cmDependsJavaParser.cxx"
break;
case 47: /* ImportDeclaration: SingleTypeImportDeclaration */
@@ -2945,7 +2957,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2949 "cmDependsJavaParser.cxx"
+#line 2961 "cmDependsJavaParser.cxx"
break;
case 48: /* ImportDeclaration: TypeImportOnDemandDeclaration */
@@ -2956,7 +2968,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2960 "cmDependsJavaParser.cxx"
+#line 2972 "cmDependsJavaParser.cxx"
break;
case 49: /* SingleTypeImportDeclaration: jp_IMPORT Name jp_SEMICOL */
@@ -2970,7 +2982,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2974 "cmDependsJavaParser.cxx"
+#line 2986 "cmDependsJavaParser.cxx"
break;
case 50: /* TypeImportOnDemandDeclaration: jp_IMPORT Name jp_DOT jp_TIMES jp_SEMICOL */
@@ -2985,7 +2997,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2989 "cmDependsJavaParser.cxx"
+#line 3001 "cmDependsJavaParser.cxx"
break;
case 51: /* TypeDeclaration: ClassDeclaration */
@@ -2996,7 +3008,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3000 "cmDependsJavaParser.cxx"
+#line 3012 "cmDependsJavaParser.cxx"
break;
case 52: /* TypeDeclaration: InterfaceDeclaration */
@@ -3007,7 +3019,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3011 "cmDependsJavaParser.cxx"
+#line 3023 "cmDependsJavaParser.cxx"
break;
case 53: /* TypeDeclaration: jp_SEMICOL */
@@ -3018,7 +3030,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3022 "cmDependsJavaParser.cxx"
+#line 3034 "cmDependsJavaParser.cxx"
break;
case 54: /* Modifiers: Modifier */
@@ -3029,7 +3041,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3033 "cmDependsJavaParser.cxx"
+#line 3045 "cmDependsJavaParser.cxx"
break;
case 55: /* Modifiers: Modifiers Modifier */
@@ -3040,7 +3052,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3044 "cmDependsJavaParser.cxx"
+#line 3056 "cmDependsJavaParser.cxx"
break;
case 67: /* ClassHeader: Modifiersopt jp_CLASS Identifier */
@@ -3051,7 +3063,7 @@ yyreduce:
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
-#line 3055 "cmDependsJavaParser.cxx"
+#line 3067 "cmDependsJavaParser.cxx"
break;
case 68: /* ClassDeclaration: ClassHeader ClassBody */
@@ -3063,7 +3075,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 3067 "cmDependsJavaParser.cxx"
+#line 3079 "cmDependsJavaParser.cxx"
break;
case 69: /* ClassDeclaration: ClassHeader Interfaces ClassBody */
@@ -3075,7 +3087,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 3079 "cmDependsJavaParser.cxx"
+#line 3091 "cmDependsJavaParser.cxx"
break;
case 70: /* ClassDeclaration: ClassHeader Super ClassBody */
@@ -3087,7 +3099,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 3091 "cmDependsJavaParser.cxx"
+#line 3103 "cmDependsJavaParser.cxx"
break;
case 71: /* ClassDeclaration: ClassHeader Super Interfaces ClassBody */
@@ -3099,7 +3111,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 3103 "cmDependsJavaParser.cxx"
+#line 3115 "cmDependsJavaParser.cxx"
break;
case 72: /* Modifiersopt: %empty */
@@ -3109,7 +3121,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3113 "cmDependsJavaParser.cxx"
+#line 3125 "cmDependsJavaParser.cxx"
break;
case 73: /* Modifiersopt: Modifiers */
@@ -3120,7 +3132,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3124 "cmDependsJavaParser.cxx"
+#line 3136 "cmDependsJavaParser.cxx"
break;
case 74: /* Super: jp_EXTENDS ClassType */
@@ -3131,7 +3143,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3135 "cmDependsJavaParser.cxx"
+#line 3147 "cmDependsJavaParser.cxx"
break;
case 75: /* Interfaces: jp_IMPLEMENTS InterfaceTypeList */
@@ -3142,7 +3154,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3146 "cmDependsJavaParser.cxx"
+#line 3158 "cmDependsJavaParser.cxx"
break;
case 76: /* InterfaceTypeList: InterfaceType */
@@ -3153,7 +3165,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3157 "cmDependsJavaParser.cxx"
+#line 3169 "cmDependsJavaParser.cxx"
break;
case 77: /* InterfaceTypeList: InterfaceTypeList jp_COMMA InterfaceType */
@@ -3164,7 +3176,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3168 "cmDependsJavaParser.cxx"
+#line 3180 "cmDependsJavaParser.cxx"
break;
case 78: /* ClassBody: jp_CURLYSTART ClassBodyDeclarations jp_CURLYEND */
@@ -3175,7 +3187,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3179 "cmDependsJavaParser.cxx"
+#line 3191 "cmDependsJavaParser.cxx"
break;
case 79: /* ClassBodyDeclarations: %empty */
@@ -3185,7 +3197,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3189 "cmDependsJavaParser.cxx"
+#line 3201 "cmDependsJavaParser.cxx"
break;
case 80: /* ClassBodyDeclarations: ClassBodyDeclarations ClassBodyDeclaration */
@@ -3196,7 +3208,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3200 "cmDependsJavaParser.cxx"
+#line 3212 "cmDependsJavaParser.cxx"
break;
case 81: /* ClassBodyDeclaration: ClassMemberDeclaration */
@@ -3207,7 +3219,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3211 "cmDependsJavaParser.cxx"
+#line 3223 "cmDependsJavaParser.cxx"
break;
case 82: /* ClassBodyDeclaration: StaticInitializer */
@@ -3218,7 +3230,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3222 "cmDependsJavaParser.cxx"
+#line 3234 "cmDependsJavaParser.cxx"
break;
case 83: /* ClassBodyDeclaration: ConstructorDeclaration */
@@ -3229,7 +3241,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3233 "cmDependsJavaParser.cxx"
+#line 3245 "cmDependsJavaParser.cxx"
break;
case 84: /* ClassBodyDeclaration: TypeDeclaration */
@@ -3240,7 +3252,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3244 "cmDependsJavaParser.cxx"
+#line 3256 "cmDependsJavaParser.cxx"
break;
case 85: /* ClassMemberDeclaration: FieldDeclaration */
@@ -3251,7 +3263,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3255 "cmDependsJavaParser.cxx"
+#line 3267 "cmDependsJavaParser.cxx"
break;
case 86: /* ClassMemberDeclaration: MethodDeclaration */
@@ -3262,7 +3274,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3266 "cmDependsJavaParser.cxx"
+#line 3278 "cmDependsJavaParser.cxx"
break;
case 87: /* FieldDeclaration: Modifiersopt Type VariableDeclarators jp_SEMICOL */
@@ -3270,7 +3282,7 @@ yyreduce:
{
jpElementStart(4);
}
-#line 3274 "cmDependsJavaParser.cxx"
+#line 3286 "cmDependsJavaParser.cxx"
break;
case 88: /* VariableDeclarators: VariableDeclarator */
@@ -3281,7 +3293,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3285 "cmDependsJavaParser.cxx"
+#line 3297 "cmDependsJavaParser.cxx"
break;
case 89: /* VariableDeclarators: VariableDeclarators jp_COMMA VariableDeclarator */
@@ -3292,7 +3304,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3296 "cmDependsJavaParser.cxx"
+#line 3308 "cmDependsJavaParser.cxx"
break;
case 90: /* VariableDeclarator: VariableDeclaratorId */
@@ -3303,7 +3315,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3307 "cmDependsJavaParser.cxx"
+#line 3319 "cmDependsJavaParser.cxx"
break;
case 91: /* VariableDeclarator: VariableDeclaratorId jp_EQUALS VariableInitializer */
@@ -3314,7 +3326,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3318 "cmDependsJavaParser.cxx"
+#line 3330 "cmDependsJavaParser.cxx"
break;
case 92: /* VariableDeclaratorId: Identifier */
@@ -3326,7 +3338,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3330 "cmDependsJavaParser.cxx"
+#line 3342 "cmDependsJavaParser.cxx"
break;
case 93: /* VariableDeclaratorId: VariableDeclaratorId jp_BRACKETSTART jp_BRACKETEND */
@@ -3337,7 +3349,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3341 "cmDependsJavaParser.cxx"
+#line 3353 "cmDependsJavaParser.cxx"
break;
case 94: /* VariableInitializer: Expression */
@@ -3348,7 +3360,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3352 "cmDependsJavaParser.cxx"
+#line 3364 "cmDependsJavaParser.cxx"
break;
case 95: /* VariableInitializer: ArrayInitializer */
@@ -3359,7 +3371,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3363 "cmDependsJavaParser.cxx"
+#line 3375 "cmDependsJavaParser.cxx"
break;
case 96: /* MethodDeclaration: MethodHeader jp_SEMICOL */
@@ -3370,7 +3382,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3374 "cmDependsJavaParser.cxx"
+#line 3386 "cmDependsJavaParser.cxx"
break;
case 97: /* MethodDeclaration: MethodHeader MethodBody */
@@ -3381,7 +3393,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3385 "cmDependsJavaParser.cxx"
+#line 3397 "cmDependsJavaParser.cxx"
break;
case 98: /* MethodDeclaration: MethodHeader MethodBody jp_SEMICOL */
@@ -3392,7 +3404,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3396 "cmDependsJavaParser.cxx"
+#line 3408 "cmDependsJavaParser.cxx"
break;
case 99: /* MethodHeader: Modifiersopt Type MethodDeclarator Throwsopt */
@@ -3404,7 +3416,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3408 "cmDependsJavaParser.cxx"
+#line 3420 "cmDependsJavaParser.cxx"
break;
case 100: /* MethodHeader: Modifiersopt jp_VOID MethodDeclarator Throwsopt */
@@ -3416,7 +3428,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3420 "cmDependsJavaParser.cxx"
+#line 3432 "cmDependsJavaParser.cxx"
break;
case 101: /* Throwsopt: %empty */
@@ -3427,7 +3439,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3431 "cmDependsJavaParser.cxx"
+#line 3443 "cmDependsJavaParser.cxx"
break;
case 102: /* Throwsopt: Throws */
@@ -3439,7 +3451,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3443 "cmDependsJavaParser.cxx"
+#line 3455 "cmDependsJavaParser.cxx"
break;
case 103: /* MethodDeclarator: Identifier jp_PARESTART FormalParameterListopt jp_PAREEND */
@@ -3452,7 +3464,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3456 "cmDependsJavaParser.cxx"
+#line 3468 "cmDependsJavaParser.cxx"
break;
case 104: /* MethodDeclarator: MethodDeclarator jp_BRACKETSTART jp_BRACKETEND */
@@ -3461,7 +3473,7 @@ yyreduce:
jpElementStart(3);
}
-#line 3465 "cmDependsJavaParser.cxx"
+#line 3477 "cmDependsJavaParser.cxx"
break;
case 105: /* FormalParameterListopt: %empty */
@@ -3472,7 +3484,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3476 "cmDependsJavaParser.cxx"
+#line 3488 "cmDependsJavaParser.cxx"
break;
case 107: /* FormalParameterList: FormalParameter */
@@ -3481,7 +3493,7 @@ yyreduce:
jpElementStart(1);
}
-#line 3485 "cmDependsJavaParser.cxx"
+#line 3497 "cmDependsJavaParser.cxx"
break;
case 108: /* FormalParameterList: FormalParameterList jp_COMMA FormalParameter */
@@ -3493,7 +3505,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3497 "cmDependsJavaParser.cxx"
+#line 3509 "cmDependsJavaParser.cxx"
break;
case 109: /* FormalParameter: Modifiersopt Type VariableDeclaratorId */
@@ -3505,7 +3517,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3509 "cmDependsJavaParser.cxx"
+#line 3521 "cmDependsJavaParser.cxx"
break;
case 110: /* Throws: jp_THROWS ClassTypeList */
@@ -3517,7 +3529,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3521 "cmDependsJavaParser.cxx"
+#line 3533 "cmDependsJavaParser.cxx"
break;
case 111: /* ClassTypeList: ClassType */
@@ -3526,7 +3538,7 @@ yyreduce:
jpElementStart(1);
}
-#line 3530 "cmDependsJavaParser.cxx"
+#line 3542 "cmDependsJavaParser.cxx"
break;
case 112: /* ClassTypeList: ClassTypeList jp_COMMA ClassType */
@@ -3538,7 +3550,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3542 "cmDependsJavaParser.cxx"
+#line 3554 "cmDependsJavaParser.cxx"
break;
case 113: /* MethodBody: Block */
@@ -3550,7 +3562,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3554 "cmDependsJavaParser.cxx"
+#line 3566 "cmDependsJavaParser.cxx"
break;
case 114: /* StaticInitializer: jp_STATIC Block */
@@ -3562,7 +3574,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3566 "cmDependsJavaParser.cxx"
+#line 3578 "cmDependsJavaParser.cxx"
break;
case 115: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody */
@@ -3574,7 +3586,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3578 "cmDependsJavaParser.cxx"
+#line 3590 "cmDependsJavaParser.cxx"
break;
case 116: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody jp_SEMICOL */
@@ -3586,7 +3598,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3590 "cmDependsJavaParser.cxx"
+#line 3602 "cmDependsJavaParser.cxx"
break;
case 117: /* ConstructorDeclarator: SimpleName jp_PARESTART FormalParameterListopt jp_PAREEND */
@@ -3599,7 +3611,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3603 "cmDependsJavaParser.cxx"
+#line 3615 "cmDependsJavaParser.cxx"
break;
case 118: /* ConstructorBody: jp_CURLYSTART ExplicitConstructorInvocationopt BlockStatementsopt jp_CURLYEND */
@@ -3611,7 +3623,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3615 "cmDependsJavaParser.cxx"
+#line 3627 "cmDependsJavaParser.cxx"
break;
case 119: /* ExplicitConstructorInvocationopt: %empty */
@@ -3622,7 +3634,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3626 "cmDependsJavaParser.cxx"
+#line 3638 "cmDependsJavaParser.cxx"
break;
case 120: /* ExplicitConstructorInvocationopt: ExplicitConstructorInvocationopt ExplicitConstructorInvocation */
@@ -3634,7 +3646,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3638 "cmDependsJavaParser.cxx"
+#line 3650 "cmDependsJavaParser.cxx"
break;
case 121: /* ExplicitConstructorInvocation: jp_THIS jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */
@@ -3646,7 +3658,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3650 "cmDependsJavaParser.cxx"
+#line 3662 "cmDependsJavaParser.cxx"
break;
case 122: /* ExplicitConstructorInvocation: jp_SUPER jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */
@@ -3658,7 +3670,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3662 "cmDependsJavaParser.cxx"
+#line 3674 "cmDependsJavaParser.cxx"
break;
case 123: /* InterfaceHeader: Modifiersopt jp_INTERFACE Identifier */
@@ -3669,7 +3681,7 @@ yyreduce:
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
-#line 3673 "cmDependsJavaParser.cxx"
+#line 3685 "cmDependsJavaParser.cxx"
break;
case 124: /* InterfaceDeclaration: InterfaceHeader ExtendsInterfacesopt InterfaceBody */
@@ -3681,7 +3693,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 3685 "cmDependsJavaParser.cxx"
+#line 3697 "cmDependsJavaParser.cxx"
break;
case 125: /* ExtendsInterfacesopt: %empty */
@@ -3691,7 +3703,7 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3695 "cmDependsJavaParser.cxx"
+#line 3707 "cmDependsJavaParser.cxx"
break;
case 126: /* ExtendsInterfacesopt: ExtendsInterfaces */
@@ -3703,7 +3715,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3707 "cmDependsJavaParser.cxx"
+#line 3719 "cmDependsJavaParser.cxx"
break;
case 127: /* ExtendsInterfaces: jp_EXTENDS InterfaceType */
@@ -3715,7 +3727,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3719 "cmDependsJavaParser.cxx"
+#line 3731 "cmDependsJavaParser.cxx"
break;
case 128: /* ExtendsInterfaces: ExtendsInterfaces jp_COMMA InterfaceType */
@@ -3727,7 +3739,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3731 "cmDependsJavaParser.cxx"
+#line 3743 "cmDependsJavaParser.cxx"
break;
case 129: /* InterfaceBody: jp_CURLYSTART InterfaceMemberDeclarations jp_CURLYEND */
@@ -3739,7 +3751,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3743 "cmDependsJavaParser.cxx"
+#line 3755 "cmDependsJavaParser.cxx"
break;
case 130: /* InterfaceMemberDeclarations: %empty */
@@ -3750,7 +3762,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3754 "cmDependsJavaParser.cxx"
+#line 3766 "cmDependsJavaParser.cxx"
break;
case 131: /* InterfaceMemberDeclarations: InterfaceMemberDeclarations InterfaceMemberDeclaration */
@@ -3761,7 +3773,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3765 "cmDependsJavaParser.cxx"
+#line 3777 "cmDependsJavaParser.cxx"
break;
case 132: /* InterfaceMemberDeclaration: ConstantDeclaration */
@@ -3773,7 +3785,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3777 "cmDependsJavaParser.cxx"
+#line 3789 "cmDependsJavaParser.cxx"
break;
case 133: /* InterfaceMemberDeclaration: AbstractMethodDeclaration */
@@ -3785,7 +3797,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3789 "cmDependsJavaParser.cxx"
+#line 3801 "cmDependsJavaParser.cxx"
break;
case 134: /* InterfaceMemberDeclaration: ClassDeclaration */
@@ -3797,7 +3809,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3801 "cmDependsJavaParser.cxx"
+#line 3813 "cmDependsJavaParser.cxx"
break;
case 135: /* InterfaceMemberDeclaration: ClassDeclaration jp_SEMICOL */
@@ -3808,7 +3820,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3812 "cmDependsJavaParser.cxx"
+#line 3824 "cmDependsJavaParser.cxx"
break;
case 136: /* InterfaceMemberDeclaration: InterfaceDeclaration */
@@ -3820,7 +3832,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3824 "cmDependsJavaParser.cxx"
+#line 3836 "cmDependsJavaParser.cxx"
break;
case 137: /* InterfaceMemberDeclaration: InterfaceDeclaration jp_SEMICOL */
@@ -3831,7 +3843,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3835 "cmDependsJavaParser.cxx"
+#line 3847 "cmDependsJavaParser.cxx"
break;
case 138: /* ConstantDeclaration: FieldDeclaration */
@@ -3843,7 +3855,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3847 "cmDependsJavaParser.cxx"
+#line 3859 "cmDependsJavaParser.cxx"
break;
case 139: /* AbstractMethodDeclaration: MethodHeader Semicols */
@@ -3855,7 +3867,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3859 "cmDependsJavaParser.cxx"
+#line 3871 "cmDependsJavaParser.cxx"
break;
case 140: /* Semicols: jp_SEMICOL */
@@ -3867,7 +3879,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3871 "cmDependsJavaParser.cxx"
+#line 3883 "cmDependsJavaParser.cxx"
break;
case 141: /* Semicols: Semicols jp_SEMICOL */
@@ -3879,7 +3891,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3883 "cmDependsJavaParser.cxx"
+#line 3895 "cmDependsJavaParser.cxx"
break;
case 142: /* ArrayInitializer: jp_CURLYSTART VariableInitializersOptional jp_CURLYEND */
@@ -3891,7 +3903,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3895 "cmDependsJavaParser.cxx"
+#line 3907 "cmDependsJavaParser.cxx"
break;
case 143: /* VariableInitializersOptional: %empty */
@@ -3902,7 +3914,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3906 "cmDependsJavaParser.cxx"
+#line 3918 "cmDependsJavaParser.cxx"
break;
case 144: /* VariableInitializersOptional: VariableInitializers */
@@ -3914,7 +3926,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3918 "cmDependsJavaParser.cxx"
+#line 3930 "cmDependsJavaParser.cxx"
break;
case 145: /* VariableInitializersOptional: VariableInitializers jp_COMMA */
@@ -3926,7 +3938,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3930 "cmDependsJavaParser.cxx"
+#line 3942 "cmDependsJavaParser.cxx"
break;
case 146: /* VariableInitializers: VariableInitializer */
@@ -3938,7 +3950,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3942 "cmDependsJavaParser.cxx"
+#line 3954 "cmDependsJavaParser.cxx"
break;
case 147: /* VariableInitializers: VariableInitializers jp_COMMA VariableInitializer */
@@ -3950,7 +3962,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3954 "cmDependsJavaParser.cxx"
+#line 3966 "cmDependsJavaParser.cxx"
break;
case 148: /* Block: jp_CURLYSTART BlockStatementsopt jp_CURLYEND */
@@ -3961,7 +3973,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3965 "cmDependsJavaParser.cxx"
+#line 3977 "cmDependsJavaParser.cxx"
break;
case 149: /* BlockStatementsopt: %empty */
@@ -3972,7 +3984,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3976 "cmDependsJavaParser.cxx"
+#line 3988 "cmDependsJavaParser.cxx"
break;
case 150: /* BlockStatementsopt: BlockStatements */
@@ -3984,7 +3996,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3988 "cmDependsJavaParser.cxx"
+#line 4000 "cmDependsJavaParser.cxx"
break;
case 151: /* BlockStatements: BlockStatement */
@@ -3996,7 +4008,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4000 "cmDependsJavaParser.cxx"
+#line 4012 "cmDependsJavaParser.cxx"
break;
case 152: /* BlockStatements: BlockStatements BlockStatement */
@@ -4008,7 +4020,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4012 "cmDependsJavaParser.cxx"
+#line 4024 "cmDependsJavaParser.cxx"
break;
case 153: /* BlockStatement: LocalVariableDeclarationStatement */
@@ -4020,7 +4032,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4024 "cmDependsJavaParser.cxx"
+#line 4036 "cmDependsJavaParser.cxx"
break;
case 154: /* BlockStatement: Statement */
@@ -4032,7 +4044,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4036 "cmDependsJavaParser.cxx"
+#line 4048 "cmDependsJavaParser.cxx"
break;
case 155: /* BlockStatement: ClassDeclaration */
@@ -4044,7 +4056,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4048 "cmDependsJavaParser.cxx"
+#line 4060 "cmDependsJavaParser.cxx"
break;
case 156: /* LocalVariableDeclarationStatement: LocalVariableDeclaration jp_SEMICOL */
@@ -4056,7 +4068,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4060 "cmDependsJavaParser.cxx"
+#line 4072 "cmDependsJavaParser.cxx"
break;
case 157: /* LocalVariableDeclaration: Modifiers Type VariableDeclarators */
@@ -4068,7 +4080,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4072 "cmDependsJavaParser.cxx"
+#line 4084 "cmDependsJavaParser.cxx"
break;
case 158: /* LocalVariableDeclaration: Type VariableDeclarators */
@@ -4080,7 +4092,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4084 "cmDependsJavaParser.cxx"
+#line 4096 "cmDependsJavaParser.cxx"
break;
case 159: /* Statement: StatementWithoutTrailingSubstatement */
@@ -4092,7 +4104,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4096 "cmDependsJavaParser.cxx"
+#line 4108 "cmDependsJavaParser.cxx"
break;
case 160: /* Statement: LabeledStatement */
@@ -4104,7 +4116,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4108 "cmDependsJavaParser.cxx"
+#line 4120 "cmDependsJavaParser.cxx"
break;
case 161: /* Statement: IfThenStatement */
@@ -4116,7 +4128,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4120 "cmDependsJavaParser.cxx"
+#line 4132 "cmDependsJavaParser.cxx"
break;
case 162: /* Statement: IfThenElseStatement */
@@ -4128,7 +4140,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4132 "cmDependsJavaParser.cxx"
+#line 4144 "cmDependsJavaParser.cxx"
break;
case 163: /* Statement: WhileStatement */
@@ -4140,7 +4152,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4144 "cmDependsJavaParser.cxx"
+#line 4156 "cmDependsJavaParser.cxx"
break;
case 164: /* Statement: ForStatement */
@@ -4152,7 +4164,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4156 "cmDependsJavaParser.cxx"
+#line 4168 "cmDependsJavaParser.cxx"
break;
case 165: /* StatementNoShortIf: StatementWithoutTrailingSubstatement */
@@ -4164,7 +4176,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4168 "cmDependsJavaParser.cxx"
+#line 4180 "cmDependsJavaParser.cxx"
break;
case 166: /* StatementNoShortIf: LabeledStatementNoShortIf */
@@ -4176,7 +4188,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4180 "cmDependsJavaParser.cxx"
+#line 4192 "cmDependsJavaParser.cxx"
break;
case 167: /* StatementNoShortIf: IfThenElseStatementNoShortIf */
@@ -4188,7 +4200,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4192 "cmDependsJavaParser.cxx"
+#line 4204 "cmDependsJavaParser.cxx"
break;
case 168: /* StatementNoShortIf: WhileStatementNoShortIf */
@@ -4200,7 +4212,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4204 "cmDependsJavaParser.cxx"
+#line 4216 "cmDependsJavaParser.cxx"
break;
case 169: /* StatementNoShortIf: ForStatementNoShortIf */
@@ -4212,7 +4224,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4216 "cmDependsJavaParser.cxx"
+#line 4228 "cmDependsJavaParser.cxx"
break;
case 170: /* StatementWithoutTrailingSubstatement: Block */
@@ -4224,7 +4236,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4228 "cmDependsJavaParser.cxx"
+#line 4240 "cmDependsJavaParser.cxx"
break;
case 171: /* StatementWithoutTrailingSubstatement: EmptyStatement */
@@ -4236,7 +4248,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4240 "cmDependsJavaParser.cxx"
+#line 4252 "cmDependsJavaParser.cxx"
break;
case 172: /* StatementWithoutTrailingSubstatement: ExpressionStatement */
@@ -4248,7 +4260,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4252 "cmDependsJavaParser.cxx"
+#line 4264 "cmDependsJavaParser.cxx"
break;
case 173: /* StatementWithoutTrailingSubstatement: SwitchStatement */
@@ -4260,7 +4272,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4264 "cmDependsJavaParser.cxx"
+#line 4276 "cmDependsJavaParser.cxx"
break;
case 174: /* StatementWithoutTrailingSubstatement: DoStatement */
@@ -4272,7 +4284,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4276 "cmDependsJavaParser.cxx"
+#line 4288 "cmDependsJavaParser.cxx"
break;
case 175: /* StatementWithoutTrailingSubstatement: BreakStatement */
@@ -4284,7 +4296,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4288 "cmDependsJavaParser.cxx"
+#line 4300 "cmDependsJavaParser.cxx"
break;
case 176: /* StatementWithoutTrailingSubstatement: ContinueStatement */
@@ -4296,7 +4308,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4300 "cmDependsJavaParser.cxx"
+#line 4312 "cmDependsJavaParser.cxx"
break;
case 177: /* StatementWithoutTrailingSubstatement: ReturnStatement */
@@ -4308,7 +4320,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4312 "cmDependsJavaParser.cxx"
+#line 4324 "cmDependsJavaParser.cxx"
break;
case 178: /* StatementWithoutTrailingSubstatement: SynchronizedStatement */
@@ -4320,7 +4332,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4324 "cmDependsJavaParser.cxx"
+#line 4336 "cmDependsJavaParser.cxx"
break;
case 179: /* StatementWithoutTrailingSubstatement: ThrowStatement */
@@ -4332,7 +4344,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4336 "cmDependsJavaParser.cxx"
+#line 4348 "cmDependsJavaParser.cxx"
break;
case 180: /* StatementWithoutTrailingSubstatement: TryStatement */
@@ -4344,7 +4356,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4348 "cmDependsJavaParser.cxx"
+#line 4360 "cmDependsJavaParser.cxx"
break;
case 181: /* StatementWithoutTrailingSubstatement: AssertStatement */
@@ -4356,7 +4368,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4360 "cmDependsJavaParser.cxx"
+#line 4372 "cmDependsJavaParser.cxx"
break;
case 182: /* EmptyStatement: jp_SEMICOL */
@@ -4368,7 +4380,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4372 "cmDependsJavaParser.cxx"
+#line 4384 "cmDependsJavaParser.cxx"
break;
case 183: /* LabeledStatement: Identifier jp_COLON Statement */
@@ -4381,7 +4393,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4385 "cmDependsJavaParser.cxx"
+#line 4397 "cmDependsJavaParser.cxx"
break;
case 184: /* LabeledStatementNoShortIf: Identifier jp_COLON StatementNoShortIf */
@@ -4393,7 +4405,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4397 "cmDependsJavaParser.cxx"
+#line 4409 "cmDependsJavaParser.cxx"
break;
case 185: /* ExpressionStatement: StatementExpression jp_SEMICOL */
@@ -4405,7 +4417,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4409 "cmDependsJavaParser.cxx"
+#line 4421 "cmDependsJavaParser.cxx"
break;
case 186: /* StatementExpression: Assignment */
@@ -4417,7 +4429,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4421 "cmDependsJavaParser.cxx"
+#line 4433 "cmDependsJavaParser.cxx"
break;
case 187: /* StatementExpression: PreIncrementExpression */
@@ -4429,7 +4441,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4433 "cmDependsJavaParser.cxx"
+#line 4445 "cmDependsJavaParser.cxx"
break;
case 188: /* StatementExpression: PreDecrementExpression */
@@ -4441,7 +4453,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4445 "cmDependsJavaParser.cxx"
+#line 4457 "cmDependsJavaParser.cxx"
break;
case 189: /* StatementExpression: PostIncrementExpression */
@@ -4453,7 +4465,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4457 "cmDependsJavaParser.cxx"
+#line 4469 "cmDependsJavaParser.cxx"
break;
case 190: /* StatementExpression: PostDecrementExpression */
@@ -4465,7 +4477,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4469 "cmDependsJavaParser.cxx"
+#line 4481 "cmDependsJavaParser.cxx"
break;
case 191: /* StatementExpression: MethodInvocation */
@@ -4477,7 +4489,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4481 "cmDependsJavaParser.cxx"
+#line 4493 "cmDependsJavaParser.cxx"
break;
case 192: /* StatementExpression: ClassInstanceCreationExpression */
@@ -4489,7 +4501,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4493 "cmDependsJavaParser.cxx"
+#line 4505 "cmDependsJavaParser.cxx"
break;
case 193: /* IfThenStatement: jp_IF jp_PARESTART Expression jp_PAREEND Statement */
@@ -4501,7 +4513,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4505 "cmDependsJavaParser.cxx"
+#line 4517 "cmDependsJavaParser.cxx"
break;
case 194: /* IfThenElseStatement: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE Statement */
@@ -4513,7 +4525,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4517 "cmDependsJavaParser.cxx"
+#line 4529 "cmDependsJavaParser.cxx"
break;
case 195: /* IfThenElseStatementNoShortIf: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE StatementNoShortIf */
@@ -4525,7 +4537,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4529 "cmDependsJavaParser.cxx"
+#line 4541 "cmDependsJavaParser.cxx"
break;
case 196: /* SwitchStatement: jp_SWITCH jp_PARESTART Expression jp_PAREEND SwitchBlock */
@@ -4534,7 +4546,7 @@ yyreduce:
jpElementStart(5);
}
-#line 4538 "cmDependsJavaParser.cxx"
+#line 4550 "cmDependsJavaParser.cxx"
break;
case 197: /* SwitchBlock: jp_CURLYSTART SwitchBlockStatementGroups SwitchLabelsopt jp_CURLYEND */
@@ -4543,7 +4555,7 @@ yyreduce:
jpElementStart(4);
}
-#line 4547 "cmDependsJavaParser.cxx"
+#line 4559 "cmDependsJavaParser.cxx"
break;
case 198: /* SwitchLabelsopt: %empty */
@@ -4554,7 +4566,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4558 "cmDependsJavaParser.cxx"
+#line 4570 "cmDependsJavaParser.cxx"
break;
case 199: /* SwitchLabelsopt: SwitchLabels */
@@ -4566,7 +4578,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4570 "cmDependsJavaParser.cxx"
+#line 4582 "cmDependsJavaParser.cxx"
break;
case 200: /* SwitchBlockStatementGroups: %empty */
@@ -4577,7 +4589,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4581 "cmDependsJavaParser.cxx"
+#line 4593 "cmDependsJavaParser.cxx"
break;
case 201: /* SwitchBlockStatementGroups: SwitchBlockStatementGroups SwitchBlockStatementGroup */
@@ -4589,7 +4601,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4593 "cmDependsJavaParser.cxx"
+#line 4605 "cmDependsJavaParser.cxx"
break;
case 202: /* SwitchBlockStatementGroup: SwitchLabels BlockStatements */
@@ -4601,7 +4613,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4605 "cmDependsJavaParser.cxx"
+#line 4617 "cmDependsJavaParser.cxx"
break;
case 203: /* SwitchLabels: SwitchLabel */
@@ -4613,7 +4625,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4617 "cmDependsJavaParser.cxx"
+#line 4629 "cmDependsJavaParser.cxx"
break;
case 204: /* SwitchLabels: SwitchLabels SwitchLabel */
@@ -4625,7 +4637,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4629 "cmDependsJavaParser.cxx"
+#line 4641 "cmDependsJavaParser.cxx"
break;
case 205: /* SwitchLabel: jp_CASE ConstantExpression jp_COLON */
@@ -4637,7 +4649,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4641 "cmDependsJavaParser.cxx"
+#line 4653 "cmDependsJavaParser.cxx"
break;
case 206: /* SwitchLabel: jp_DEFAULT jp_COLON */
@@ -4649,7 +4661,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4653 "cmDependsJavaParser.cxx"
+#line 4665 "cmDependsJavaParser.cxx"
break;
case 207: /* WhileStatement: jp_WHILE jp_PARESTART Expression jp_PAREEND Statement */
@@ -4658,7 +4670,7 @@ yyreduce:
jpElementStart(5);
}
-#line 4662 "cmDependsJavaParser.cxx"
+#line 4674 "cmDependsJavaParser.cxx"
break;
case 208: /* WhileStatementNoShortIf: jp_WHILE jp_PARESTART Expression jp_PAREEND StatementNoShortIf */
@@ -4667,7 +4679,7 @@ yyreduce:
jpElementStart(5);
}
-#line 4671 "cmDependsJavaParser.cxx"
+#line 4683 "cmDependsJavaParser.cxx"
break;
case 209: /* DoStatement: jp_DO Statement jp_WHILE jp_PARESTART Expression jp_PAREEND jp_SEMICOL */
@@ -4676,7 +4688,7 @@ yyreduce:
jpElementStart(7);
}
-#line 4680 "cmDependsJavaParser.cxx"
+#line 4692 "cmDependsJavaParser.cxx"
break;
case 210: /* ForStatement: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND Statement */
@@ -4685,7 +4697,7 @@ yyreduce:
jpElementStart(9);
}
-#line 4689 "cmDependsJavaParser.cxx"
+#line 4701 "cmDependsJavaParser.cxx"
break;
case 211: /* ForUpdateopt: %empty */
@@ -4696,7 +4708,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4700 "cmDependsJavaParser.cxx"
+#line 4712 "cmDependsJavaParser.cxx"
break;
case 212: /* ForUpdateopt: ForUpdate */
@@ -4708,7 +4720,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4712 "cmDependsJavaParser.cxx"
+#line 4724 "cmDependsJavaParser.cxx"
break;
case 213: /* ForInitopt: %empty */
@@ -4719,7 +4731,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4723 "cmDependsJavaParser.cxx"
+#line 4735 "cmDependsJavaParser.cxx"
break;
case 214: /* ForInitopt: ForInit */
@@ -4731,7 +4743,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4735 "cmDependsJavaParser.cxx"
+#line 4747 "cmDependsJavaParser.cxx"
break;
case 215: /* ForStatementNoShortIf: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND StatementNoShortIf */
@@ -4742,7 +4754,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4746 "cmDependsJavaParser.cxx"
+#line 4758 "cmDependsJavaParser.cxx"
break;
case 216: /* Expressionopt: %empty */
@@ -4753,7 +4765,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4757 "cmDependsJavaParser.cxx"
+#line 4769 "cmDependsJavaParser.cxx"
break;
case 217: /* Expressionopt: Expression */
@@ -4765,7 +4777,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4769 "cmDependsJavaParser.cxx"
+#line 4781 "cmDependsJavaParser.cxx"
break;
case 218: /* ForInit: StatementExpressionList */
@@ -4777,7 +4789,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4781 "cmDependsJavaParser.cxx"
+#line 4793 "cmDependsJavaParser.cxx"
break;
case 219: /* ForInit: LocalVariableDeclaration */
@@ -4789,7 +4801,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4793 "cmDependsJavaParser.cxx"
+#line 4805 "cmDependsJavaParser.cxx"
break;
case 220: /* ForUpdate: StatementExpressionList */
@@ -4801,7 +4813,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4805 "cmDependsJavaParser.cxx"
+#line 4817 "cmDependsJavaParser.cxx"
break;
case 221: /* StatementExpressionList: StatementExpression */
@@ -4813,7 +4825,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4817 "cmDependsJavaParser.cxx"
+#line 4829 "cmDependsJavaParser.cxx"
break;
case 222: /* StatementExpressionList: StatementExpressionList jp_COMMA StatementExpression */
@@ -4825,7 +4837,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4829 "cmDependsJavaParser.cxx"
+#line 4841 "cmDependsJavaParser.cxx"
break;
case 223: /* AssertStatement: jp_ASSERT Expression jp_SEMICOL */
@@ -4837,7 +4849,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4841 "cmDependsJavaParser.cxx"
+#line 4853 "cmDependsJavaParser.cxx"
break;
case 224: /* AssertStatement: jp_ASSERT Expression jp_COLON Expression jp_SEMICOL */
@@ -4849,7 +4861,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4853 "cmDependsJavaParser.cxx"
+#line 4865 "cmDependsJavaParser.cxx"
break;
case 225: /* BreakStatement: jp_BREAK Identifieropt jp_SEMICOL */
@@ -4862,7 +4874,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4866 "cmDependsJavaParser.cxx"
+#line 4878 "cmDependsJavaParser.cxx"
break;
case 226: /* Identifieropt: %empty */
@@ -4873,7 +4885,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4877 "cmDependsJavaParser.cxx"
+#line 4889 "cmDependsJavaParser.cxx"
break;
case 227: /* Identifieropt: Identifier */
@@ -4882,7 +4894,7 @@ yyreduce:
jpElementStart(1);
}
-#line 4886 "cmDependsJavaParser.cxx"
+#line 4898 "cmDependsJavaParser.cxx"
break;
case 228: /* ContinueStatement: jp_CONTINUE Identifieropt jp_SEMICOL */
@@ -4895,7 +4907,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4899 "cmDependsJavaParser.cxx"
+#line 4911 "cmDependsJavaParser.cxx"
break;
case 229: /* ReturnStatement: jp_RETURN Expressionopt jp_SEMICOL */
@@ -4907,7 +4919,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4911 "cmDependsJavaParser.cxx"
+#line 4923 "cmDependsJavaParser.cxx"
break;
case 230: /* ThrowStatement: jp_THROW Expression jp_SEMICOL */
@@ -4919,7 +4931,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4923 "cmDependsJavaParser.cxx"
+#line 4935 "cmDependsJavaParser.cxx"
break;
case 231: /* SynchronizedStatement: jp_SYNCHRONIZED jp_PARESTART Expression jp_PAREEND Block */
@@ -4931,7 +4943,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4935 "cmDependsJavaParser.cxx"
+#line 4947 "cmDependsJavaParser.cxx"
break;
case 232: /* TryStatement: jp_TRY Block Catches */
@@ -4943,7 +4955,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4947 "cmDependsJavaParser.cxx"
+#line 4959 "cmDependsJavaParser.cxx"
break;
case 233: /* TryStatement: jp_TRY Block Catchesopt Finally */
@@ -4955,7 +4967,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4959 "cmDependsJavaParser.cxx"
+#line 4971 "cmDependsJavaParser.cxx"
break;
case 234: /* Catchesopt: %empty */
@@ -4966,7 +4978,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4970 "cmDependsJavaParser.cxx"
+#line 4982 "cmDependsJavaParser.cxx"
break;
case 235: /* Catchesopt: Catches */
@@ -4978,7 +4990,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4982 "cmDependsJavaParser.cxx"
+#line 4994 "cmDependsJavaParser.cxx"
break;
case 236: /* Catches: CatchClause */
@@ -4990,7 +5002,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4994 "cmDependsJavaParser.cxx"
+#line 5006 "cmDependsJavaParser.cxx"
break;
case 237: /* Catches: Catches CatchClause */
@@ -5002,7 +5014,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5006 "cmDependsJavaParser.cxx"
+#line 5018 "cmDependsJavaParser.cxx"
break;
case 238: /* CatchClause: jp_CATCH jp_PARESTART FormalParameter jp_PAREEND Block */
@@ -5011,7 +5023,7 @@ yyreduce:
jpElementStart(5);
}
-#line 5015 "cmDependsJavaParser.cxx"
+#line 5027 "cmDependsJavaParser.cxx"
break;
case 239: /* Finally: jp_FINALLY Block */
@@ -5023,7 +5035,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5027 "cmDependsJavaParser.cxx"
+#line 5039 "cmDependsJavaParser.cxx"
break;
case 240: /* Primary: PrimaryNoNewArray */
@@ -5035,7 +5047,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5039 "cmDependsJavaParser.cxx"
+#line 5051 "cmDependsJavaParser.cxx"
break;
case 241: /* Primary: ArrayCreationExpression */
@@ -5047,7 +5059,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5051 "cmDependsJavaParser.cxx"
+#line 5063 "cmDependsJavaParser.cxx"
break;
case 242: /* PrimaryNoNewArray: Literal */
@@ -5059,7 +5071,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5063 "cmDependsJavaParser.cxx"
+#line 5075 "cmDependsJavaParser.cxx"
break;
case 243: /* PrimaryNoNewArray: jp_THIS */
@@ -5068,7 +5080,7 @@ yyreduce:
jpElementStart(1);
}
-#line 5072 "cmDependsJavaParser.cxx"
+#line 5084 "cmDependsJavaParser.cxx"
break;
case 244: /* PrimaryNoNewArray: jp_PARESTART Expression jp_PAREEND */
@@ -5080,7 +5092,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5084 "cmDependsJavaParser.cxx"
+#line 5096 "cmDependsJavaParser.cxx"
break;
case 245: /* PrimaryNoNewArray: ClassInstanceCreationExpression */
@@ -5092,7 +5104,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5096 "cmDependsJavaParser.cxx"
+#line 5108 "cmDependsJavaParser.cxx"
break;
case 246: /* PrimaryNoNewArray: FieldAccess */
@@ -5104,7 +5116,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5108 "cmDependsJavaParser.cxx"
+#line 5120 "cmDependsJavaParser.cxx"
break;
case 247: /* PrimaryNoNewArray: MethodInvocation */
@@ -5116,7 +5128,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5120 "cmDependsJavaParser.cxx"
+#line 5132 "cmDependsJavaParser.cxx"
break;
case 248: /* PrimaryNoNewArray: ArrayAccess */
@@ -5128,7 +5140,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5132 "cmDependsJavaParser.cxx"
+#line 5144 "cmDependsJavaParser.cxx"
break;
case 249: /* ClassInstanceCreationExpression: New ClassType jp_PARESTART ArgumentListopt jp_PAREEND ClassBodyOpt */
@@ -5140,7 +5152,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5144 "cmDependsJavaParser.cxx"
+#line 5156 "cmDependsJavaParser.cxx"
break;
case 250: /* ClassBodyOpt: %empty */
@@ -5151,7 +5163,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5155 "cmDependsJavaParser.cxx"
+#line 5167 "cmDependsJavaParser.cxx"
break;
case 251: /* ClassBodyOpt: ClassBody */
@@ -5163,7 +5175,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5167 "cmDependsJavaParser.cxx"
+#line 5179 "cmDependsJavaParser.cxx"
break;
case 252: /* ArgumentListopt: %empty */
@@ -5174,7 +5186,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5178 "cmDependsJavaParser.cxx"
+#line 5190 "cmDependsJavaParser.cxx"
break;
case 253: /* ArgumentListopt: ArgumentList */
@@ -5186,7 +5198,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5190 "cmDependsJavaParser.cxx"
+#line 5202 "cmDependsJavaParser.cxx"
break;
case 254: /* ArgumentList: Expression */
@@ -5198,7 +5210,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5202 "cmDependsJavaParser.cxx"
+#line 5214 "cmDependsJavaParser.cxx"
break;
case 255: /* ArgumentList: ArgumentList jp_COMMA Expression */
@@ -5210,7 +5222,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5214 "cmDependsJavaParser.cxx"
+#line 5226 "cmDependsJavaParser.cxx"
break;
case 256: /* ArrayCreationExpression: New PrimitiveType DimExprs Dimsopt */
@@ -5222,7 +5234,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5226 "cmDependsJavaParser.cxx"
+#line 5238 "cmDependsJavaParser.cxx"
break;
case 257: /* ArrayCreationExpression: New ClassOrInterfaceType DimExprs Dimsopt */
@@ -5234,7 +5246,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5238 "cmDependsJavaParser.cxx"
+#line 5250 "cmDependsJavaParser.cxx"
break;
case 258: /* ArrayCreationExpression: New PrimitiveType Dims ArrayInitializer */
@@ -5246,7 +5258,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5250 "cmDependsJavaParser.cxx"
+#line 5262 "cmDependsJavaParser.cxx"
break;
case 259: /* ArrayCreationExpression: New ClassOrInterfaceType Dims ArrayInitializer */
@@ -5258,7 +5270,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5262 "cmDependsJavaParser.cxx"
+#line 5274 "cmDependsJavaParser.cxx"
break;
case 260: /* Dimsopt: %empty */
@@ -5269,7 +5281,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5273 "cmDependsJavaParser.cxx"
+#line 5285 "cmDependsJavaParser.cxx"
break;
case 261: /* Dimsopt: Dims */
@@ -5281,7 +5293,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5285 "cmDependsJavaParser.cxx"
+#line 5297 "cmDependsJavaParser.cxx"
break;
case 262: /* DimExprs: DimExpr */
@@ -5293,7 +5305,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5297 "cmDependsJavaParser.cxx"
+#line 5309 "cmDependsJavaParser.cxx"
break;
case 263: /* DimExprs: DimExprs DimExpr */
@@ -5305,7 +5317,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5309 "cmDependsJavaParser.cxx"
+#line 5321 "cmDependsJavaParser.cxx"
break;
case 264: /* DimExpr: jp_BRACKETSTART Expression jp_BRACKETEND */
@@ -5317,7 +5329,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5321 "cmDependsJavaParser.cxx"
+#line 5333 "cmDependsJavaParser.cxx"
break;
case 265: /* Dims: jp_BRACKETSTART jp_BRACKETEND */
@@ -5326,7 +5338,7 @@ yyreduce:
jpElementStart(2);
}
-#line 5330 "cmDependsJavaParser.cxx"
+#line 5342 "cmDependsJavaParser.cxx"
break;
case 266: /* Dims: Dims jp_BRACKETSTART jp_BRACKETEND */
@@ -5335,7 +5347,7 @@ yyreduce:
jpElementStart(3);
}
-#line 5339 "cmDependsJavaParser.cxx"
+#line 5351 "cmDependsJavaParser.cxx"
break;
case 267: /* FieldAccess: Primary jp_DOT Identifier */
@@ -5348,7 +5360,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5352 "cmDependsJavaParser.cxx"
+#line 5364 "cmDependsJavaParser.cxx"
break;
case 268: /* FieldAccess: jp_SUPER jp_DOT Identifier */
@@ -5361,7 +5373,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5365 "cmDependsJavaParser.cxx"
+#line 5377 "cmDependsJavaParser.cxx"
break;
case 269: /* FieldAccess: jp_THIS jp_DOT Identifier */
@@ -5374,7 +5386,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5378 "cmDependsJavaParser.cxx"
+#line 5390 "cmDependsJavaParser.cxx"
break;
case 270: /* FieldAccess: Primary jp_DOT jp_THIS */
@@ -5387,7 +5399,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5391 "cmDependsJavaParser.cxx"
+#line 5403 "cmDependsJavaParser.cxx"
break;
case 271: /* MethodInvocation: Name jp_PARESTART ArgumentListopt jp_PAREEND */
@@ -5400,7 +5412,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5404 "cmDependsJavaParser.cxx"
+#line 5416 "cmDependsJavaParser.cxx"
break;
case 272: /* MethodInvocation: Primary jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */
@@ -5414,7 +5426,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5418 "cmDependsJavaParser.cxx"
+#line 5430 "cmDependsJavaParser.cxx"
break;
case 273: /* MethodInvocation: jp_SUPER jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */
@@ -5427,7 +5439,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5431 "cmDependsJavaParser.cxx"
+#line 5443 "cmDependsJavaParser.cxx"
break;
case 274: /* MethodInvocation: jp_THIS jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */
@@ -5440,7 +5452,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5444 "cmDependsJavaParser.cxx"
+#line 5456 "cmDependsJavaParser.cxx"
break;
case 275: /* ArrayAccess: Name jp_BRACKETSTART Expression jp_BRACKETEND */
@@ -5453,7 +5465,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5457 "cmDependsJavaParser.cxx"
+#line 5469 "cmDependsJavaParser.cxx"
break;
case 276: /* ArrayAccess: PrimaryNoNewArray jp_BRACKETSTART Expression jp_BRACKETEND */
@@ -5465,7 +5477,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5469 "cmDependsJavaParser.cxx"
+#line 5481 "cmDependsJavaParser.cxx"
break;
case 277: /* PostfixExpression: Primary */
@@ -5477,7 +5489,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5481 "cmDependsJavaParser.cxx"
+#line 5493 "cmDependsJavaParser.cxx"
break;
case 278: /* PostfixExpression: Name */
@@ -5489,7 +5501,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5493 "cmDependsJavaParser.cxx"
+#line 5505 "cmDependsJavaParser.cxx"
break;
case 279: /* PostfixExpression: ArrayType jp_DOT jp_CLASS */
@@ -5501,7 +5513,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5505 "cmDependsJavaParser.cxx"
+#line 5517 "cmDependsJavaParser.cxx"
break;
case 280: /* PostfixExpression: PostIncrementExpression */
@@ -5513,7 +5525,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5517 "cmDependsJavaParser.cxx"
+#line 5529 "cmDependsJavaParser.cxx"
break;
case 281: /* PostfixExpression: PostDecrementExpression */
@@ -5525,7 +5537,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5529 "cmDependsJavaParser.cxx"
+#line 5541 "cmDependsJavaParser.cxx"
break;
case 282: /* PostIncrementExpression: PostfixExpression jp_PLUSPLUS */
@@ -5537,7 +5549,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5541 "cmDependsJavaParser.cxx"
+#line 5553 "cmDependsJavaParser.cxx"
break;
case 283: /* PostDecrementExpression: PostfixExpression jp_MINUSMINUS */
@@ -5549,7 +5561,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5553 "cmDependsJavaParser.cxx"
+#line 5565 "cmDependsJavaParser.cxx"
break;
case 284: /* UnaryExpression: PreIncrementExpression */
@@ -5561,7 +5573,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5565 "cmDependsJavaParser.cxx"
+#line 5577 "cmDependsJavaParser.cxx"
break;
case 285: /* UnaryExpression: PreDecrementExpression */
@@ -5573,7 +5585,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5577 "cmDependsJavaParser.cxx"
+#line 5589 "cmDependsJavaParser.cxx"
break;
case 286: /* UnaryExpression: jp_PLUS UnaryExpression */
@@ -5585,7 +5597,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5589 "cmDependsJavaParser.cxx"
+#line 5601 "cmDependsJavaParser.cxx"
break;
case 287: /* UnaryExpression: jp_MINUS UnaryExpression */
@@ -5597,7 +5609,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5601 "cmDependsJavaParser.cxx"
+#line 5613 "cmDependsJavaParser.cxx"
break;
case 288: /* UnaryExpression: UnaryExpressionNotPlusMinus */
@@ -5609,7 +5621,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5613 "cmDependsJavaParser.cxx"
+#line 5625 "cmDependsJavaParser.cxx"
break;
case 289: /* PreIncrementExpression: jp_PLUSPLUS UnaryExpression */
@@ -5621,7 +5633,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5625 "cmDependsJavaParser.cxx"
+#line 5637 "cmDependsJavaParser.cxx"
break;
case 290: /* PreDecrementExpression: jp_MINUSMINUS UnaryExpression */
@@ -5633,7 +5645,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5637 "cmDependsJavaParser.cxx"
+#line 5649 "cmDependsJavaParser.cxx"
break;
case 291: /* UnaryExpressionNotPlusMinus: PostfixExpression */
@@ -5645,7 +5657,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5649 "cmDependsJavaParser.cxx"
+#line 5661 "cmDependsJavaParser.cxx"
break;
case 292: /* UnaryExpressionNotPlusMinus: jp_TILDE UnaryExpression */
@@ -5657,7 +5669,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5661 "cmDependsJavaParser.cxx"
+#line 5673 "cmDependsJavaParser.cxx"
break;
case 293: /* UnaryExpressionNotPlusMinus: jp_EXCLAMATION UnaryExpression */
@@ -5669,7 +5681,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5673 "cmDependsJavaParser.cxx"
+#line 5685 "cmDependsJavaParser.cxx"
break;
case 294: /* UnaryExpressionNotPlusMinus: CastExpression */
@@ -5681,7 +5693,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5685 "cmDependsJavaParser.cxx"
+#line 5697 "cmDependsJavaParser.cxx"
break;
case 295: /* CastExpression: jp_PARESTART PrimitiveType Dimsopt jp_PAREEND UnaryExpression */
@@ -5693,7 +5705,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5697 "cmDependsJavaParser.cxx"
+#line 5709 "cmDependsJavaParser.cxx"
break;
case 296: /* CastExpression: jp_PARESTART Expression jp_PAREEND UnaryExpressionNotPlusMinus */
@@ -5705,7 +5717,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5709 "cmDependsJavaParser.cxx"
+#line 5721 "cmDependsJavaParser.cxx"
break;
case 297: /* CastExpression: jp_PARESTART Name Dims jp_PAREEND UnaryExpressionNotPlusMinus */
@@ -5714,7 +5726,7 @@ yyreduce:
jpElementStart(5);
}
-#line 5718 "cmDependsJavaParser.cxx"
+#line 5730 "cmDependsJavaParser.cxx"
break;
case 298: /* MultiplicativeExpression: UnaryExpression */
@@ -5726,7 +5738,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5730 "cmDependsJavaParser.cxx"
+#line 5742 "cmDependsJavaParser.cxx"
break;
case 299: /* MultiplicativeExpression: MultiplicativeExpression jp_TIMES UnaryExpression */
@@ -5738,7 +5750,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5742 "cmDependsJavaParser.cxx"
+#line 5754 "cmDependsJavaParser.cxx"
break;
case 300: /* MultiplicativeExpression: MultiplicativeExpression jp_DIVIDE UnaryExpression */
@@ -5750,7 +5762,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5754 "cmDependsJavaParser.cxx"
+#line 5766 "cmDependsJavaParser.cxx"
break;
case 301: /* MultiplicativeExpression: MultiplicativeExpression jp_PERCENT UnaryExpression */
@@ -5762,7 +5774,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5766 "cmDependsJavaParser.cxx"
+#line 5778 "cmDependsJavaParser.cxx"
break;
case 302: /* AdditiveExpression: MultiplicativeExpression */
@@ -5774,7 +5786,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5778 "cmDependsJavaParser.cxx"
+#line 5790 "cmDependsJavaParser.cxx"
break;
case 303: /* AdditiveExpression: AdditiveExpression jp_PLUS MultiplicativeExpression */
@@ -5786,7 +5798,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5790 "cmDependsJavaParser.cxx"
+#line 5802 "cmDependsJavaParser.cxx"
break;
case 304: /* AdditiveExpression: AdditiveExpression jp_MINUS MultiplicativeExpression */
@@ -5798,7 +5810,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5802 "cmDependsJavaParser.cxx"
+#line 5814 "cmDependsJavaParser.cxx"
break;
case 305: /* ShiftExpression: AdditiveExpression */
@@ -5810,7 +5822,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5814 "cmDependsJavaParser.cxx"
+#line 5826 "cmDependsJavaParser.cxx"
break;
case 306: /* ShiftExpression: ShiftExpression jp_LTLT AdditiveExpression */
@@ -5822,7 +5834,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5826 "cmDependsJavaParser.cxx"
+#line 5838 "cmDependsJavaParser.cxx"
break;
case 307: /* ShiftExpression: ShiftExpression jp_GTGT AdditiveExpression */
@@ -5834,7 +5846,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5838 "cmDependsJavaParser.cxx"
+#line 5850 "cmDependsJavaParser.cxx"
break;
case 308: /* ShiftExpression: ShiftExpression jp_GTGTGT AdditiveExpression */
@@ -5846,7 +5858,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5850 "cmDependsJavaParser.cxx"
+#line 5862 "cmDependsJavaParser.cxx"
break;
case 309: /* RelationalExpression: ShiftExpression */
@@ -5858,7 +5870,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5862 "cmDependsJavaParser.cxx"
+#line 5874 "cmDependsJavaParser.cxx"
break;
case 310: /* RelationalExpression: RelationalExpression jp_LESSTHAN ShiftExpression */
@@ -5870,7 +5882,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5874 "cmDependsJavaParser.cxx"
+#line 5886 "cmDependsJavaParser.cxx"
break;
case 311: /* RelationalExpression: RelationalExpression jp_GREATER ShiftExpression */
@@ -5882,7 +5894,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5886 "cmDependsJavaParser.cxx"
+#line 5898 "cmDependsJavaParser.cxx"
break;
case 312: /* RelationalExpression: RelationalExpression jp_LTEQUALS ShiftExpression */
@@ -5894,7 +5906,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5898 "cmDependsJavaParser.cxx"
+#line 5910 "cmDependsJavaParser.cxx"
break;
case 313: /* RelationalExpression: RelationalExpression jp_GTEQUALS ShiftExpression */
@@ -5906,7 +5918,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5910 "cmDependsJavaParser.cxx"
+#line 5922 "cmDependsJavaParser.cxx"
break;
case 314: /* RelationalExpression: RelationalExpression jp_INSTANCEOF ReferenceType */
@@ -5918,7 +5930,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5922 "cmDependsJavaParser.cxx"
+#line 5934 "cmDependsJavaParser.cxx"
break;
case 315: /* EqualityExpression: RelationalExpression */
@@ -5930,7 +5942,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5934 "cmDependsJavaParser.cxx"
+#line 5946 "cmDependsJavaParser.cxx"
break;
case 316: /* EqualityExpression: EqualityExpression jp_EQUALSEQUALS RelationalExpression */
@@ -5942,7 +5954,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5946 "cmDependsJavaParser.cxx"
+#line 5958 "cmDependsJavaParser.cxx"
break;
case 317: /* EqualityExpression: EqualityExpression jp_EXCLAMATIONEQUALS RelationalExpression */
@@ -5954,7 +5966,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5958 "cmDependsJavaParser.cxx"
+#line 5970 "cmDependsJavaParser.cxx"
break;
case 318: /* AndExpression: EqualityExpression */
@@ -5966,7 +5978,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5970 "cmDependsJavaParser.cxx"
+#line 5982 "cmDependsJavaParser.cxx"
break;
case 319: /* AndExpression: AndExpression jp_AND EqualityExpression */
@@ -5978,7 +5990,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5982 "cmDependsJavaParser.cxx"
+#line 5994 "cmDependsJavaParser.cxx"
break;
case 320: /* ExclusiveOrExpression: AndExpression */
@@ -5990,7 +6002,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5994 "cmDependsJavaParser.cxx"
+#line 6006 "cmDependsJavaParser.cxx"
break;
case 321: /* ExclusiveOrExpression: ExclusiveOrExpression jp_CARROT AndExpression */
@@ -6002,7 +6014,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6006 "cmDependsJavaParser.cxx"
+#line 6018 "cmDependsJavaParser.cxx"
break;
case 322: /* InclusiveOrExpression: ExclusiveOrExpression */
@@ -6014,7 +6026,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6018 "cmDependsJavaParser.cxx"
+#line 6030 "cmDependsJavaParser.cxx"
break;
case 323: /* InclusiveOrExpression: InclusiveOrExpression jp_PIPE ExclusiveOrExpression */
@@ -6026,7 +6038,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6030 "cmDependsJavaParser.cxx"
+#line 6042 "cmDependsJavaParser.cxx"
break;
case 324: /* ConditionalAndExpression: InclusiveOrExpression */
@@ -6038,7 +6050,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6042 "cmDependsJavaParser.cxx"
+#line 6054 "cmDependsJavaParser.cxx"
break;
case 325: /* ConditionalAndExpression: ConditionalAndExpression jp_ANDAND InclusiveOrExpression */
@@ -6050,7 +6062,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6054 "cmDependsJavaParser.cxx"
+#line 6066 "cmDependsJavaParser.cxx"
break;
case 326: /* ConditionalOrExpression: ConditionalAndExpression */
@@ -6062,7 +6074,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6066 "cmDependsJavaParser.cxx"
+#line 6078 "cmDependsJavaParser.cxx"
break;
case 327: /* ConditionalOrExpression: ConditionalOrExpression jp_PIPEPIPE ConditionalAndExpression */
@@ -6074,7 +6086,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6078 "cmDependsJavaParser.cxx"
+#line 6090 "cmDependsJavaParser.cxx"
break;
case 328: /* ConditionalExpression: ConditionalOrExpression */
@@ -6086,7 +6098,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6090 "cmDependsJavaParser.cxx"
+#line 6102 "cmDependsJavaParser.cxx"
break;
case 329: /* ConditionalExpression: ConditionalOrExpression jp_QUESTION Expression jp_COLON ConditionalExpression */
@@ -6098,7 +6110,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6102 "cmDependsJavaParser.cxx"
+#line 6114 "cmDependsJavaParser.cxx"
break;
case 330: /* AssignmentExpression: ConditionalExpression */
@@ -6110,7 +6122,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6114 "cmDependsJavaParser.cxx"
+#line 6126 "cmDependsJavaParser.cxx"
break;
case 331: /* AssignmentExpression: Assignment */
@@ -6122,7 +6134,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6126 "cmDependsJavaParser.cxx"
+#line 6138 "cmDependsJavaParser.cxx"
break;
case 332: /* Assignment: LeftHandSide AssignmentOperator AssignmentExpression */
@@ -6134,7 +6146,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6138 "cmDependsJavaParser.cxx"
+#line 6150 "cmDependsJavaParser.cxx"
break;
case 333: /* LeftHandSide: Name */
@@ -6147,7 +6159,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6151 "cmDependsJavaParser.cxx"
+#line 6163 "cmDependsJavaParser.cxx"
break;
case 334: /* LeftHandSide: FieldAccess */
@@ -6159,7 +6171,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6163 "cmDependsJavaParser.cxx"
+#line 6175 "cmDependsJavaParser.cxx"
break;
case 335: /* LeftHandSide: ArrayAccess */
@@ -6171,7 +6183,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6175 "cmDependsJavaParser.cxx"
+#line 6187 "cmDependsJavaParser.cxx"
break;
case 336: /* AssignmentOperator: jp_EQUALS */
@@ -6183,7 +6195,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6187 "cmDependsJavaParser.cxx"
+#line 6199 "cmDependsJavaParser.cxx"
break;
case 337: /* AssignmentOperator: jp_TIMESEQUALS */
@@ -6195,7 +6207,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6199 "cmDependsJavaParser.cxx"
+#line 6211 "cmDependsJavaParser.cxx"
break;
case 338: /* AssignmentOperator: jp_DIVIDEEQUALS */
@@ -6207,7 +6219,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6211 "cmDependsJavaParser.cxx"
+#line 6223 "cmDependsJavaParser.cxx"
break;
case 339: /* AssignmentOperator: jp_PERCENTEQUALS */
@@ -6219,7 +6231,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6223 "cmDependsJavaParser.cxx"
+#line 6235 "cmDependsJavaParser.cxx"
break;
case 340: /* AssignmentOperator: jp_PLUSEQUALS */
@@ -6231,7 +6243,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6235 "cmDependsJavaParser.cxx"
+#line 6247 "cmDependsJavaParser.cxx"
break;
case 341: /* AssignmentOperator: jp_MINUSEQUALS */
@@ -6243,7 +6255,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6247 "cmDependsJavaParser.cxx"
+#line 6259 "cmDependsJavaParser.cxx"
break;
case 342: /* AssignmentOperator: jp_LESLESEQUALS */
@@ -6255,7 +6267,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6259 "cmDependsJavaParser.cxx"
+#line 6271 "cmDependsJavaParser.cxx"
break;
case 343: /* AssignmentOperator: jp_GTGTEQUALS */
@@ -6267,7 +6279,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6271 "cmDependsJavaParser.cxx"
+#line 6283 "cmDependsJavaParser.cxx"
break;
case 344: /* AssignmentOperator: jp_GTGTGTEQUALS */
@@ -6279,7 +6291,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6283 "cmDependsJavaParser.cxx"
+#line 6295 "cmDependsJavaParser.cxx"
break;
case 345: /* AssignmentOperator: jp_ANDEQUALS */
@@ -6291,7 +6303,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6295 "cmDependsJavaParser.cxx"
+#line 6307 "cmDependsJavaParser.cxx"
break;
case 346: /* AssignmentOperator: jp_CARROTEQUALS */
@@ -6303,7 +6315,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6307 "cmDependsJavaParser.cxx"
+#line 6319 "cmDependsJavaParser.cxx"
break;
case 347: /* AssignmentOperator: jp_PIPEEQUALS */
@@ -6315,7 +6327,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6319 "cmDependsJavaParser.cxx"
+#line 6331 "cmDependsJavaParser.cxx"
break;
case 348: /* Expression: AssignmentExpression */
@@ -6327,7 +6339,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6331 "cmDependsJavaParser.cxx"
+#line 6343 "cmDependsJavaParser.cxx"
break;
case 349: /* ConstantExpression: Expression */
@@ -6339,7 +6351,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6343 "cmDependsJavaParser.cxx"
+#line 6355 "cmDependsJavaParser.cxx"
break;
case 350: /* New: jp_NEW */
@@ -6351,7 +6363,7 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6355 "cmDependsJavaParser.cxx"
+#line 6367 "cmDependsJavaParser.cxx"
break;
case 351: /* New: Name jp_DOT jp_NEW */
@@ -6364,11 +6376,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6368 "cmDependsJavaParser.cxx"
+#line 6380 "cmDependsJavaParser.cxx"
break;
-#line 6372 "cmDependsJavaParser.cxx"
+#line 6384 "cmDependsJavaParser.cxx"
default: break;
}
diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h
index 4ae55fa3b..885cc66e7 100644
--- a/Source/LexerParser/cmDependsJavaParserTokens.h
+++ b/Source/LexerParser/cmDependsJavaParserTokens.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.4. */
+/* A Bison parser, made by GNU Bison 3.7.5. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/Source/LexerParser/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx
index 72e59b689..5a76590a1 100644
--- a/Source/LexerParser/cmExprLexer.cxx
+++ b/Source/LexerParser/cmExprLexer.cxx
@@ -664,7 +664,7 @@ Modify cmExprLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include "cmExprParserHelper.h"
diff --git a/Source/LexerParser/cmExprLexer.in.l b/Source/LexerParser/cmExprLexer.in.l
index f8a422431..90c1cc3ab 100644
--- a/Source/LexerParser/cmExprLexer.in.l
+++ b/Source/LexerParser/cmExprLexer.in.l
@@ -18,7 +18,7 @@ Modify cmExprLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include "cmExprParserHelper.h"
diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx
index b747d8b13..d9b0ae3ca 100644
--- a/Source/LexerParser/cmExprParser.cxx
+++ b/Source/LexerParser/cmExprParser.cxx
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.4. */
+/* A Bison parser, made by GNU Bison 3.7.5. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -46,10 +46,10 @@
USER NAME SPACE" below. */
/* Identify Bison output, and Bison version. */
-#define YYBISON 30704
+#define YYBISON 30705
/* Bison version string. */
-#define YYBISON_VERSION "3.7.4"
+#define YYBISON_VERSION "3.7.5"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -120,7 +120,11 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
# endif
#endif
-#line 124 "cmExprParser.cxx"
+#if defined(__NVCOMPILER)
+# pragma diag_suppress 550 /* variable set but never used */
+#endif
+
+#line 128 "cmExprParser.cxx"
# ifndef YY_CAST
# ifdef __cplusplus
@@ -218,6 +222,18 @@ typedef int_least16_t yytype_int16;
typedef short yytype_int16;
#endif
+/* Work around bug in HP-UX 11.23, which defines these macros
+ incorrectly for preprocessor constants. This workaround can likely
+ be removed in 2023, as HPE has promised support for HP-UX 11.23
+ (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
+ <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */
+#ifdef __hpux
+# undef UINT_LEAST8_MAX
+# undef UINT_LEAST16_MAX
+# define UINT_LEAST8_MAX 255
+# define UINT_LEAST16_MAX 65535
+#endif
+
#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
@@ -315,9 +331,9 @@ typedef int yy_state_fast_t;
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
+# define YY_USE(E) ((void) (E))
#else
-# define YYUSE(E) /* empty */
+# define YY_USE(E) /* empty */
#endif
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
@@ -544,9 +560,9 @@ static const yytype_int8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 81, 81, 86, 89, 94, 97, 102, 105, 110,
- 113, 116, 121, 124, 127, 132, 135, 138, 144, 149,
- 152, 155, 158, 163, 166
+ 0, 85, 85, 90, 93, 98, 101, 106, 109, 114,
+ 117, 120, 125, 128, 131, 136, 139, 142, 148, 153,
+ 156, 159, 162, 167, 170
};
#endif
@@ -629,7 +645,7 @@ static const yytype_int8 yypgoto[] =
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ 0, 6, 7, 8, 9, 10, 11, 12, 13, 14
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
@@ -754,8 +770,8 @@ yy_symbol_value_print (FILE *yyo,
yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
FILE *yyoutput = yyo;
- YYUSE (yyoutput);
- YYUSE (yyscanner);
+ YY_USE (yyoutput);
+ YY_USE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
@@ -763,7 +779,7 @@ yy_symbol_value_print (FILE *yyo,
YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yykind);
+ YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -1144,14 +1160,14 @@ static void
yydestruct (const char *yymsg,
yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
- YYUSE (yyvaluep);
- YYUSE (yyscanner);
+ YY_USE (yyvaluep);
+ YY_USE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yykind);
+ YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -1421,194 +1437,194 @@ yyreduce:
switch (yyn)
{
case 2: /* start: exp */
-#line 81 "cmExprParser.y"
+#line 85 "cmExprParser.y"
{
cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
}
-#line 1429 "cmExprParser.cxx"
+#line 1445 "cmExprParser.cxx"
break;
case 3: /* exp: bitwiseor */
-#line 86 "cmExprParser.y"
+#line 90 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1437 "cmExprParser.cxx"
+#line 1453 "cmExprParser.cxx"
break;
case 4: /* exp: exp exp_OR bitwiseor */
-#line 89 "cmExprParser.y"
+#line 93 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
}
-#line 1445 "cmExprParser.cxx"
+#line 1461 "cmExprParser.cxx"
break;
case 5: /* bitwiseor: bitwisexor */
-#line 94 "cmExprParser.y"
+#line 98 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1453 "cmExprParser.cxx"
+#line 1469 "cmExprParser.cxx"
break;
case 6: /* bitwiseor: bitwiseor exp_XOR bitwisexor */
-#line 97 "cmExprParser.y"
+#line 101 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
}
-#line 1461 "cmExprParser.cxx"
+#line 1477 "cmExprParser.cxx"
break;
case 7: /* bitwisexor: bitwiseand */
-#line 102 "cmExprParser.y"
+#line 106 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1469 "cmExprParser.cxx"
+#line 1485 "cmExprParser.cxx"
break;
case 8: /* bitwisexor: bitwisexor exp_AND bitwiseand */
-#line 105 "cmExprParser.y"
+#line 109 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
}
-#line 1477 "cmExprParser.cxx"
+#line 1493 "cmExprParser.cxx"
break;
case 9: /* bitwiseand: shift */
-#line 110 "cmExprParser.y"
+#line 114 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1485 "cmExprParser.cxx"
+#line 1501 "cmExprParser.cxx"
break;
case 10: /* bitwiseand: bitwiseand exp_SHIFTLEFT shift */
-#line 113 "cmExprParser.y"
+#line 117 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
}
-#line 1493 "cmExprParser.cxx"
+#line 1509 "cmExprParser.cxx"
break;
case 11: /* bitwiseand: bitwiseand exp_SHIFTRIGHT shift */
-#line 116 "cmExprParser.y"
+#line 120 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
}
-#line 1501 "cmExprParser.cxx"
+#line 1517 "cmExprParser.cxx"
break;
case 12: /* shift: term */
-#line 121 "cmExprParser.y"
+#line 125 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1509 "cmExprParser.cxx"
+#line 1525 "cmExprParser.cxx"
break;
case 13: /* shift: shift exp_PLUS term */
-#line 124 "cmExprParser.y"
+#line 128 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
}
-#line 1517 "cmExprParser.cxx"
+#line 1533 "cmExprParser.cxx"
break;
case 14: /* shift: shift exp_MINUS term */
-#line 127 "cmExprParser.y"
+#line 131 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
}
-#line 1525 "cmExprParser.cxx"
+#line 1541 "cmExprParser.cxx"
break;
case 15: /* term: unary */
-#line 132 "cmExprParser.y"
+#line 136 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1533 "cmExprParser.cxx"
+#line 1549 "cmExprParser.cxx"
break;
case 16: /* term: term exp_TIMES unary */
-#line 135 "cmExprParser.y"
+#line 139 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
}
-#line 1541 "cmExprParser.cxx"
+#line 1557 "cmExprParser.cxx"
break;
case 17: /* term: term exp_DIVIDE unary */
-#line 138 "cmExprParser.y"
+#line 142 "cmExprParser.y"
{
if (yyvsp[0].Number == 0) {
throw std::overflow_error("divide by zero");
}
(yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
}
-#line 1552 "cmExprParser.cxx"
+#line 1568 "cmExprParser.cxx"
break;
case 18: /* term: term exp_MOD unary */
-#line 144 "cmExprParser.y"
+#line 148 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
}
-#line 1560 "cmExprParser.cxx"
+#line 1576 "cmExprParser.cxx"
break;
case 19: /* unary: factor */
-#line 149 "cmExprParser.y"
+#line 153 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1568 "cmExprParser.cxx"
+#line 1584 "cmExprParser.cxx"
break;
case 20: /* unary: exp_PLUS unary */
-#line 152 "cmExprParser.y"
+#line 156 "cmExprParser.y"
{
(yyval.Number) = + (yyvsp[0].Number);
}
-#line 1576 "cmExprParser.cxx"
+#line 1592 "cmExprParser.cxx"
break;
case 21: /* unary: exp_MINUS unary */
-#line 155 "cmExprParser.y"
+#line 159 "cmExprParser.y"
{
(yyval.Number) = - (yyvsp[0].Number);
}
-#line 1584 "cmExprParser.cxx"
+#line 1600 "cmExprParser.cxx"
break;
case 22: /* unary: exp_NOT unary */
-#line 158 "cmExprParser.y"
+#line 162 "cmExprParser.y"
{
(yyval.Number) = ~ (yyvsp[0].Number);
}
-#line 1592 "cmExprParser.cxx"
+#line 1608 "cmExprParser.cxx"
break;
case 23: /* factor: exp_NUMBER */
-#line 163 "cmExprParser.y"
+#line 167 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1600 "cmExprParser.cxx"
+#line 1616 "cmExprParser.cxx"
break;
case 24: /* factor: exp_OPENPARENT exp exp_CLOSEPARENT */
-#line 166 "cmExprParser.y"
+#line 170 "cmExprParser.y"
{
(yyval.Number) = (yyvsp[-1].Number);
}
-#line 1608 "cmExprParser.cxx"
+#line 1624 "cmExprParser.cxx"
break;
-#line 1612 "cmExprParser.cxx"
+#line 1628 "cmExprParser.cxx"
default: break;
}
@@ -1833,7 +1849,7 @@ yyreturn:
return yyresult;
}
-#line 171 "cmExprParser.y"
+#line 175 "cmExprParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y
index b49f48212..fda2395b0 100644
--- a/Source/LexerParser/cmExprParser.y
+++ b/Source/LexerParser/cmExprParser.y
@@ -44,6 +44,10 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
# pragma clang diagnostic ignored "-Wused-but-marked-unused"
# endif
#endif
+
+#if defined(__NVCOMPILER)
+# pragma diag_suppress 550 /* variable set but never used */
+#endif
%}
/* Generate a reentrant parser object. */
diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h
index 2eb1fe928..67b03def9 100644
--- a/Source/LexerParser/cmExprParserTokens.h
+++ b/Source/LexerParser/cmExprParserTokens.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.4. */
+/* A Bison parser, made by GNU Bison 3.7.5. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/Source/LexerParser/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx
index bcda77c30..c3d000004 100644
--- a/Source/LexerParser/cmFortranLexer.cxx
+++ b/Source/LexerParser/cmFortranLexer.cxx
@@ -838,7 +838,7 @@ Modify cmFortranLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#undef YY_NO_UNPUT
diff --git a/Source/LexerParser/cmFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l
index 3d38a7dad..05769a1e3 100644
--- a/Source/LexerParser/cmFortranLexer.in.l
+++ b/Source/LexerParser/cmFortranLexer.in.l
@@ -27,7 +27,7 @@ Modify cmFortranLexer.cxx:
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#undef YY_NO_UNPUT
diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index dba2cac13..3f3dddeb4 100644
--- a/Source/LexerParser/cmFortranParser.cxx
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.4. */
+/* A Bison parser, made by GNU Bison 3.7.5. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -46,10 +46,10 @@
USER NAME SPACE" below. */
/* Identify Bison output, and Bison version. */
-#define YYBISON 30704
+#define YYBISON 30705
/* Bison version string. */
-#define YYBISON_VERSION "3.7.4"
+#define YYBISON_VERSION "3.7.5"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -259,6 +259,18 @@ typedef int_least16_t yytype_int16;
typedef short yytype_int16;
#endif
+/* Work around bug in HP-UX 11.23, which defines these macros
+ incorrectly for preprocessor constants. This workaround can likely
+ be removed in 2023, as HPE has promised support for HP-UX 11.23
+ (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
+ <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */
+#ifdef __hpux
+# undef UINT_LEAST8_MAX
+# undef UINT_LEAST16_MAX
+# define UINT_LEAST8_MAX 255
+# define UINT_LEAST16_MAX 65535
+#endif
+
#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
@@ -356,9 +368,9 @@ typedef int yy_state_fast_t;
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
+# define YY_USE(E) ((void) (E))
#else
-# define YYUSE(E) /* empty */
+# define YY_USE(E) /* empty */
#endif
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
@@ -587,13 +599,13 @@ static const yytype_int8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 99, 99, 99, 102, 106, 111, 120, 126, 133,
- 138, 142, 147, 155, 160, 165, 170, 175, 180, 185,
- 190, 195, 199, 203, 207, 211, 212, 217, 217, 217,
- 218, 218, 219, 219, 220, 220, 221, 221, 222, 222,
- 223, 223, 224, 224, 225, 225, 226, 226, 229, 230,
- 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
- 241, 242, 243, 244, 245
+ 0, 101, 101, 101, 104, 108, 113, 122, 128, 135,
+ 140, 144, 149, 157, 162, 167, 172, 177, 182, 187,
+ 192, 197, 201, 205, 209, 213, 214, 219, 219, 219,
+ 220, 220, 221, 221, 222, 222, 223, 223, 224, 224,
+ 225, 225, 226, 226, 227, 227, 228, 228, 231, 232,
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
+ 243, 244, 245, 246, 247
};
#endif
@@ -701,7 +713,7 @@ static const yytype_int8 yypgoto[] =
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 1, 32, 33, 34, 35, 36, 37, 38, 39,
+ 0, 1, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 44, 82
};
@@ -955,8 +967,8 @@ yy_symbol_value_print (FILE *yyo,
yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
FILE *yyoutput = yyo;
- YYUSE (yyoutput);
- YYUSE (yyscanner);
+ YY_USE (yyoutput);
+ YY_USE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
@@ -964,7 +976,7 @@ yy_symbol_value_print (FILE *yyo,
YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yykind);
+ YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -1345,14 +1357,36 @@ static void
yydestruct (const char *yymsg,
yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
- YYUSE (yyvaluep);
- YYUSE (yyscanner);
+ YY_USE (yyvaluep);
+ YY_USE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yykind);
+ switch (yykind)
+ {
+ case YYSYMBOL_STRING: /* STRING */
+#line 95 "cmFortranParser.y"
+ { free(((*yyvaluep).string)); }
+#line 1373 "cmFortranParser.cxx"
+ break;
+
+ case YYSYMBOL_WORD: /* WORD */
+#line 95 "cmFortranParser.y"
+ { free(((*yyvaluep).string)); }
+#line 1379 "cmFortranParser.cxx"
+ break;
+
+ case YYSYMBOL_CPP_INCLUDE_ANGLE: /* CPP_INCLUDE_ANGLE */
+#line 95 "cmFortranParser.y"
+ { free(((*yyvaluep).string)); }
+#line 1385 "cmFortranParser.cxx"
+ break;
+
+ default:
+ break;
+ }
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -1622,26 +1656,26 @@ yyreduce:
switch (yyn)
{
case 4: /* stmt: INTERFACE EOSTMT */
-#line 102 "cmFortranParser.y"
+#line 104 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
}
-#line 1631 "cmFortranParser.cxx"
+#line 1665 "cmFortranParser.cxx"
break;
case 5: /* stmt: USE WORD other EOSTMT */
-#line 106 "cmFortranParser.y"
+#line 108 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1641 "cmFortranParser.cxx"
+#line 1675 "cmFortranParser.cxx"
break;
case 6: /* stmt: MODULE WORD other EOSTMT */
-#line 111 "cmFortranParser.y"
+#line 113 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
@@ -1651,22 +1685,22 @@ yyreduce:
}
free((yyvsp[-2].string));
}
-#line 1655 "cmFortranParser.cxx"
+#line 1689 "cmFortranParser.cxx"
break;
case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT */
-#line 120 "cmFortranParser.y"
+#line 122 "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));
}
-#line 1666 "cmFortranParser.cxx"
+#line 1700 "cmFortranParser.cxx"
break;
case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT */
-#line 126 "cmFortranParser.y"
+#line 128 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string));
@@ -1674,40 +1708,40 @@ yyreduce:
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1678 "cmFortranParser.cxx"
+#line 1712 "cmFortranParser.cxx"
break;
case 9: /* stmt: INTERFACE WORD other EOSTMT */
-#line 133 "cmFortranParser.y"
+#line 135 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
free((yyvsp[-2].string));
}
-#line 1688 "cmFortranParser.cxx"
+#line 1722 "cmFortranParser.cxx"
break;
case 10: /* stmt: END INTERFACE other EOSTMT */
-#line 138 "cmFortranParser.y"
+#line 140 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, false);
}
-#line 1697 "cmFortranParser.cxx"
+#line 1731 "cmFortranParser.cxx"
break;
case 11: /* stmt: USE DCOLON WORD other EOSTMT */
-#line 142 "cmFortranParser.y"
+#line 144 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1707 "cmFortranParser.cxx"
+#line 1741 "cmFortranParser.cxx"
break;
case 12: /* stmt: USE COMMA WORD DCOLON WORD other EOSTMT */
-#line 147 "cmFortranParser.y"
+#line 149 "cmFortranParser.y"
{
if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
@@ -1716,139 +1750,139 @@ yyreduce:
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1720 "cmFortranParser.cxx"
+#line 1754 "cmFortranParser.cxx"
break;
case 13: /* stmt: INCLUDE STRING other EOSTMT */
-#line 155 "cmFortranParser.y"
+#line 157 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1730 "cmFortranParser.cxx"
+#line 1764 "cmFortranParser.cxx"
break;
case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */
-#line 160 "cmFortranParser.y"
+#line 162 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1740 "cmFortranParser.cxx"
+#line 1774 "cmFortranParser.cxx"
break;
case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */
-#line 165 "cmFortranParser.y"
+#line 167 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1750 "cmFortranParser.cxx"
+#line 1784 "cmFortranParser.cxx"
break;
case 16: /* stmt: include STRING other EOSTMT */
-#line 170 "cmFortranParser.y"
+#line 172 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1760 "cmFortranParser.cxx"
+#line 1794 "cmFortranParser.cxx"
break;
case 17: /* stmt: define WORD other EOSTMT */
-#line 175 "cmFortranParser.y"
+#line 177 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1770 "cmFortranParser.cxx"
+#line 1804 "cmFortranParser.cxx"
break;
case 18: /* stmt: undef WORD other EOSTMT */
-#line 180 "cmFortranParser.y"
+#line 182 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1780 "cmFortranParser.cxx"
+#line 1814 "cmFortranParser.cxx"
break;
case 19: /* stmt: ifdef WORD other EOSTMT */
-#line 185 "cmFortranParser.y"
+#line 187 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1790 "cmFortranParser.cxx"
+#line 1824 "cmFortranParser.cxx"
break;
case 20: /* stmt: ifndef WORD other EOSTMT */
-#line 190 "cmFortranParser.y"
+#line 192 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1800 "cmFortranParser.cxx"
+#line 1834 "cmFortranParser.cxx"
break;
case 21: /* stmt: if other EOSTMT */
-#line 195 "cmFortranParser.y"
+#line 197 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIf(parser);
}
-#line 1809 "cmFortranParser.cxx"
+#line 1843 "cmFortranParser.cxx"
break;
case 22: /* stmt: elif other EOSTMT */
-#line 199 "cmFortranParser.y"
+#line 201 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElif(parser);
}
-#line 1818 "cmFortranParser.cxx"
+#line 1852 "cmFortranParser.cxx"
break;
case 23: /* stmt: else other EOSTMT */
-#line 203 "cmFortranParser.y"
+#line 205 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElse(parser);
}
-#line 1827 "cmFortranParser.cxx"
+#line 1861 "cmFortranParser.cxx"
break;
case 24: /* stmt: endif other EOSTMT */
-#line 207 "cmFortranParser.y"
+#line 209 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleEndif(parser);
}
-#line 1836 "cmFortranParser.cxx"
+#line 1870 "cmFortranParser.cxx"
break;
case 48: /* misc_code: WORD */
-#line 229 "cmFortranParser.y"
+#line 231 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
-#line 1842 "cmFortranParser.cxx"
+#line 1876 "cmFortranParser.cxx"
break;
case 55: /* misc_code: STRING */
-#line 236 "cmFortranParser.y"
+#line 238 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
-#line 1848 "cmFortranParser.cxx"
+#line 1882 "cmFortranParser.cxx"
break;
-#line 1852 "cmFortranParser.cxx"
+#line 1886 "cmFortranParser.cxx"
default: break;
}
@@ -2073,6 +2107,6 @@ yyreturn:
return yyresult;
}
-#line 248 "cmFortranParser.y"
+#line 250 "cmFortranParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y
index e461160c6..a3e1c24b1 100644
--- a/Source/LexerParser/cmFortranParser.y
+++ b/Source/LexerParser/cmFortranParser.y
@@ -92,6 +92,8 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
%token SUBMODULE
%token USE
+%destructor { free($$); } WORD STRING CPP_INCLUDE_ANGLE
+
/*-------------------------------------------------------------------------*/
/* grammar */
%%
diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h
index e250110c0..3a19cfb1d 100644
--- a/Source/LexerParser/cmFortranParserTokens.h
+++ b/Source/LexerParser/cmFortranParserTokens.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.4. */
+/* A Bison parser, made by GNU Bison 3.7.5. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/Source/LexerParser/cmGccDepfileLexer.cxx b/Source/LexerParser/cmGccDepfileLexer.cxx
index 3630f4ef8..194ae0c49 100644
--- a/Source/LexerParser/cmGccDepfileLexer.cxx
+++ b/Source/LexerParser/cmGccDepfileLexer.cxx
@@ -645,7 +645,7 @@ static const flex_int16_t yy_chk[46] =
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include <cmGccDepfileLexerHelper.h>
#include <string>
diff --git a/Source/LexerParser/cmGccDepfileLexer.in.l b/Source/LexerParser/cmGccDepfileLexer.in.l
index c83cb75e8..aa2351e84 100644
--- a/Source/LexerParser/cmGccDepfileLexer.in.l
+++ b/Source/LexerParser/cmGccDepfileLexer.in.l
@@ -4,7 +4,7 @@
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */
#include <cmGccDepfileLexerHelper.h>
#include <string>
diff --git a/Source/Modules/FindLibUUID.cmake b/Source/Modules/FindLibUUID.cmake
index 17f11c1f5..ca5b61d1c 100644
--- a/Source/Modules/FindLibUUID.cmake
+++ b/Source/Modules/FindLibUUID.cmake
@@ -40,7 +40,14 @@ They may be set by end users to point at LibUUID components.
#]=======================================================================]
#-----------------------------------------------------------------------------
-if(CYGWIN)
+if(MSYS)
+ # Note: on current version of MSYS2, linking to libuuid.dll.a doesn't
+ # import the right symbols sometimes. Fix this by linking directly
+ # to the DLL that provides the symbols, instead.
+ find_library(LibUUID_LIBRARY
+ NAMES msys-uuid-1.dll
+ )
+elseif(CYGWIN)
# Note: on current version of Cygwin, linking to libuuid.dll.a doesn't
# import the right symbols sometimes. Fix this by linking directly
# to the DLL that provides the symbols, instead.
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index 5debdb89b..8ffa3e728 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -112,7 +112,10 @@ int main(int argc, char** argv)
cmAddPluginPath();
#endif
-#if QT_VERSION >= 0x050600
+// HighDpiScaling is always enabled starting with Qt6, but will still issue a
+// deprecation warning if you try to set the attribute for it
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) && \
+ QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
@@ -132,9 +135,9 @@ int main(int argc, char** argv)
translationsDir.cd(QString::fromLocal8Bit(".." CMAKE_DATA_DIR));
translationsDir.cd("i18n");
QTranslator translator;
- QString transfile = QString("cmake_%1").arg(QLocale::system().name());
- translator.load(transfile, translationsDir.path());
- QApplication::installTranslator(&translator);
+ if (translator.load(QLocale(), "cmake", "_", translationsDir.path())) {
+ QApplication::installTranslator(&translator);
+ }
// app setup
QApplication::setApplicationName("CMakeSetup");
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 031308891..178557168 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -178,7 +178,11 @@ CMakeSetupDialog::CMakeSetupDialog()
&CMakeSetupDialog::doOutputErrorNext);
a->setShortcut(QKeySequence(Qt::Key_F8));
auto* s = new QShortcut(this);
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
s->setKey(QKeySequence(Qt::CTRL + Qt::Key_Period));
+#else
+ s->setKey(QKeySequence(Qt::CTRL | Qt::Key_Period));
+#endif
QObject::connect(s, &QShortcut::activated, this,
&CMakeSetupDialog::doOutputErrorNext); // in Eclipse
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index f593f8358..e6faef470 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -13,6 +13,7 @@
#include "cmExternalMakefileProjectGenerator.h"
#include "cmGlobalGenerator.h"
+#include "cmMessageMetadata.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -37,8 +38,8 @@ QCMake::QCMake(QObject* p)
cmSystemTools::SetRunCommandHideConsole(true);
cmSystemTools::SetMessageCallback(
- [this](std::string const& msg, const char* title) {
- this->messageCallback(msg, title);
+ [this](std::string const& msg, const cmMessageMetadata& md) {
+ this->messageCallback(msg, md.title);
});
cmSystemTools::SetStdoutCallback(
[this](std::string const& msg) { this->stdoutCallback(msg); });
@@ -160,7 +161,7 @@ void QCMake::setPreset(const QString& name, bool setBinary)
auto const& expandedPreset =
this->CMakePresetsFile.ConfigurePresets[presetName].Expanded;
if (expandedPreset) {
- if (setBinary) {
+ if (setBinary && !expandedPreset->BinaryDir.empty()) {
QString binaryDir =
QString::fromLocal8Bit(expandedPreset->BinaryDir.data());
this->setBinaryDirectory(binaryDir);
@@ -334,7 +335,12 @@ void QCMake::setProperties(const QCMakePropertyList& newProps)
toremove.append(QString::fromLocal8Bit(key.c_str()));
} else {
prop = props[idx];
- if (prop.Value.type() == QVariant::Bool) {
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
+ const bool isBool = prop.Value.type() == QVariant::Bool;
+#else
+ const bool isBool = prop.Value.metaType() == QMetaType::fromType<bool>();
+#endif
+ if (isBool) {
state->SetCacheEntryValue(key, prop.Value.toBool() ? "ON" : "OFF");
} else {
state->SetCacheEntryValue(key,
@@ -557,7 +563,7 @@ void QCMake::loadPresets()
preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data()));
preset.setToolset = !p.ToolsetStrategy ||
p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
- preset.enabled = it.Expanded &&
+ preset.enabled = it.Expanded && it.Expanded->ConditionResult &&
std::find_if(this->AvailableGenerators.begin(),
this->AvailableGenerators.end(),
[&p](const cmake::GeneratorInfo& g) {
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index b685b73af..54b299824 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -2,11 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmArchiveWrite.h"
-#include <cstdio>
+#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
+#include <limits>
#include <sstream>
+#include <string>
+#include <thread>
+
+#include <cm/algorithm>
#include <cm3p/archive.h>
#include <cm3p/archive_entry.h>
@@ -144,16 +149,36 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
cm_archive_error_string(this->Archive));
return;
}
+
{
- char sNumThreads[8];
- snprintf(sNumThreads, sizeof(sNumThreads), "%d", numThreads);
- sNumThreads[7] = '\0'; // for safety
+#if ARCHIVE_VERSION_NUMBER >= 3004000
+ // Upstream fixed an issue with their integer parsing in 3.4.0
+ // which would cause spurious errors to be raised from `strtoull`.
+
+ if (numThreads < 1) {
+ int upperLimit = (numThreads == 0) ? std::numeric_limits<int>::max()
+ : std::abs(numThreads);
+
+ numThreads =
+ cm::clamp<int>(std::thread::hardware_concurrency(), 1, upperLimit);
+ }
+
+# ifdef _AIX
+ // FIXME: Using more than 2 threads creates an empty archive.
+ // Enforce this limit pending further investigation.
+ numThreads = std::min(numThreads, 2);
+# endif
+
+ std::string sNumThreads = std::to_string(numThreads);
+
if (archive_write_set_filter_option(this->Archive, "xz", "threads",
- sNumThreads) != ARCHIVE_OK) {
+ sNumThreads.c_str()) !=
+ ARCHIVE_OK) {
this->Error = cmStrCat("archive_compressor_xz_options: ",
cm_archive_error_string(this->Archive));
return;
}
+#endif
}
break;
@@ -425,16 +450,3 @@ bool cmArchiveWrite::AddData(const char* file, size_t size)
}
return true;
}
-
-bool cmArchiveWrite::SetFilterOption(const char* module, const char* key,
- const char* value)
-{
- if (archive_write_set_filter_option(this->Archive, module, key, value) !=
- ARCHIVE_OK) {
- this->Error = "archive_write_set_filter_option: ";
- this->Error += cm_archive_error_string(this->Archive);
- return false;
- }
-
- return true;
-}
diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h
index 34aafe905..260bd20ca 100644
--- a/Source/cmArchiveWrite.h
+++ b/Source/cmArchiveWrite.h
@@ -141,9 +141,6 @@ public:
this->Gname = "";
}
- //! Set an option on a filter;
- bool SetFilterOption(const char* module, const char* key, const char* value);
-
private:
bool Okay() const { return this->Error.empty(); }
bool AddPath(const char* path, size_t skip, const char* prefix,
diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx
index 9ce403dcc..99707a3f7 100644
--- a/Source/cmBinUtilsLinuxELFLinker.cxx
+++ b/Source/cmBinUtilsLinuxELFLinker.cxx
@@ -18,6 +18,10 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#ifdef CMake_USE_ELF_PARSER
+# include "cmELF.h"
+#endif
+
static std::string ReplaceOrigin(const std::string& rpath,
const std::string& origin)
{
@@ -86,6 +90,24 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies(
std::string const& file, cmStateEnums::TargetType /* unused */)
{
std::vector<std::string> parentRpaths;
+
+#ifdef CMake_USE_ELF_PARSER
+ cmELF elf(file.c_str());
+ if (!elf) {
+ return false;
+ }
+ if (elf.GetMachine() != 0) {
+ if (this->Machine != 0) {
+ if (elf.GetMachine() != this->Machine) {
+ this->SetError("All files must have the same architecture.");
+ return false;
+ }
+ } else {
+ this->Machine = elf.GetMachine();
+ }
+ }
+#endif
+
return this->ScanDependencies(file, parentRpaths);
}
@@ -150,13 +172,29 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies(
return true;
}
+namespace {
+bool FileHasArchitecture(const char* filename, std::uint16_t machine)
+{
+#ifdef CMake_USE_ELF_PARSER
+ cmELF elf(filename);
+ if (!elf) {
+ return false;
+ }
+ return machine == 0 || machine == elf.GetMachine();
+#else
+ return true;
+#endif
+}
+}
+
bool cmBinUtilsLinuxELFLinker::ResolveDependency(
std::string const& name, std::vector<std::string> const& searchPaths,
std::string& path, bool& resolved)
{
for (auto const& searchPath : searchPaths) {
path = cmStrCat(searchPath, '/', name);
- if (cmSystemTools::PathExists(path)) {
+ if (cmSystemTools::PathExists(path) &&
+ FileHasArchitecture(path.c_str(), this->Machine)) {
resolved = true;
return true;
}
@@ -164,7 +202,8 @@ bool cmBinUtilsLinuxELFLinker::ResolveDependency(
for (auto const& searchPath : this->Archive->GetSearchDirectories()) {
path = cmStrCat(searchPath, '/', name);
- if (cmSystemTools::PathExists(path)) {
+ if (cmSystemTools::PathExists(path) &&
+ FileHasArchitecture(path.c_str(), this->Machine)) {
std::ostringstream warning;
warning << "Dependency " << name << " found in search directory:\n "
<< searchPath
diff --git a/Source/cmBinUtilsLinuxELFLinker.h b/Source/cmBinUtilsLinuxELFLinker.h
index 4e7e36d4c..395ed567b 100644
--- a/Source/cmBinUtilsLinuxELFLinker.h
+++ b/Source/cmBinUtilsLinuxELFLinker.h
@@ -3,6 +3,9 @@
#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstdint>
#include <memory>
#include <string>
#include <vector>
@@ -29,6 +32,7 @@ private:
std::unique_ptr<cmLDConfigTool> LDConfigTool;
bool HaveLDConfigPaths = false;
std::vector<std::string> LDConfigPaths;
+ std::uint16_t Machine = 0;
bool ScanDependencies(std::string const& file,
std::vector<std::string> const& parentRpaths);
diff --git a/Source/cmBinUtilsMacOSMachOLinker.cxx b/Source/cmBinUtilsMacOSMachOLinker.cxx
index 0f47146c5..47f77d8b9 100644
--- a/Source/cmBinUtilsMacOSMachOLinker.cxx
+++ b/Source/cmBinUtilsMacOSMachOLinker.cxx
@@ -65,18 +65,18 @@ bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
if (!executableFile.empty()) {
executablePath = cmSystemTools::GetFilenamePath(executableFile);
}
- return this->ScanDependencies(file, executablePath);
-}
-
-bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
- std::string const& file, std::string const& executablePath)
-{
std::vector<std::string> libs;
std::vector<std::string> rpaths;
if (!this->Tool->GetFileInfo(file, libs, rpaths)) {
return false;
}
+ return this->ScanDependencies(file, libs, rpaths, executablePath);
+}
+bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
+ std::string const& file, std::vector<std::string> const& libs,
+ std::vector<std::string> const& rpaths, std::string const& executablePath)
+{
std::string loaderPath = cmSystemTools::GetFilenamePath(file);
return this->GetFileDependencies(libs, executablePath, loaderPath, rpaths);
}
@@ -98,8 +98,14 @@ bool cmBinUtilsMacOSMachOLinker::GetFileDependencies(
!IsMissingSystemDylib(path)) {
auto filename = cmSystemTools::GetFilenameName(path);
bool unique;
- this->Archive->AddResolvedPath(filename, path, unique);
- if (unique && !this->ScanDependencies(path, executablePath)) {
+ std::vector<std::string> libs;
+ std::vector<std::string> depRpaths;
+ if (!this->Tool->GetFileInfo(path, libs, depRpaths)) {
+ return false;
+ }
+ this->Archive->AddResolvedPath(filename, path, unique, depRpaths);
+ if (unique &&
+ !this->ScanDependencies(path, libs, depRpaths, executablePath)) {
return false;
}
}
diff --git a/Source/cmBinUtilsMacOSMachOLinker.h b/Source/cmBinUtilsMacOSMachOLinker.h
index 1c4a5fcd3..eae23cc88 100644
--- a/Source/cmBinUtilsMacOSMachOLinker.h
+++ b/Source/cmBinUtilsMacOSMachOLinker.h
@@ -27,6 +27,8 @@ private:
std::unique_ptr<cmBinUtilsMacOSMachOGetRuntimeDependenciesTool> Tool;
bool ScanDependencies(std::string const& file,
+ std::vector<std::string> const& libs,
+ std::vector<std::string> const& rpaths,
std::string const& executablePath);
bool GetFileDependencies(std::vector<std::string> const& names,
diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
index 1effda053..f14de5596 100644
--- a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
+++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
@@ -8,6 +8,7 @@
#include <cmsys/RegularExpression.hxx>
#include "cmRuntimeDependencyArchive.h"
+#include "cmSystemTools.h"
#include "cmUVProcessChain.h"
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::
@@ -42,8 +43,8 @@ bool cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::GetFileInfo(
std::string line;
static const cmsys::RegularExpression regex(
- "^\t*DLL Name: ([^\n]*\\.[Dd][Ll][Ll])\r$");
- while (std::getline(*process.OutputStream(), line)) {
+ "^\t*DLL Name: ([^\n]*\\.[Dd][Ll][Ll])$");
+ while (cmSystemTools::GetLineFromStream(*process.OutputStream(), line)) {
cmsys::RegularExpressionMatch match;
if (regex.find(line.c_str(), match)) {
needed.push_back(match.match(1));
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index 2eaf31561..56b080aa6 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -28,12 +28,14 @@ bool MainSignature(std::vector<std::string> const& args,
std::string configuration;
std::string project_name;
std::string target;
+ std::string parallel;
enum Doing
{
DoingNone,
DoingConfiguration,
DoingProjectName,
- DoingTarget
+ DoingTarget,
+ DoingParallel
};
Doing doing = DoingNone;
for (unsigned int i = 1; i < args.size(); ++i) {
@@ -43,6 +45,8 @@ bool MainSignature(std::vector<std::string> const& args,
doing = DoingProjectName;
} else if (args[i] == "TARGET") {
doing = DoingTarget;
+ } else if (args[i] == "PARALLEL_LEVEL") {
+ doing = DoingParallel;
} else if (doing == DoingConfiguration) {
doing = DoingNone;
configuration = args[i];
@@ -52,6 +56,9 @@ bool MainSignature(std::vector<std::string> const& args,
} else if (doing == DoingTarget) {
doing = DoingNone;
target = args[i];
+ } else if (doing == DoingParallel) {
+ doing = DoingNone;
+ parallel = args[i];
} else {
status.SetError(cmStrCat("unknown argument \"", args[i], "\""));
return false;
@@ -77,7 +84,7 @@ bool MainSignature(std::vector<std::string> const& args,
}
std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand(
- target, configuration, "", mf.IgnoreErrorsCMP0061());
+ target, configuration, parallel, "", mf.IgnoreErrorsCMP0061());
mf.AddDefinition(variable, makecommand);
@@ -104,7 +111,7 @@ bool TwoArgsSignature(std::vector<std::string> const& args,
}
std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand(
- "", configType, "", mf.IgnoreErrorsCMP0061());
+ "", configType, "", "", mf.IgnoreErrorsCMP0061());
if (cacheValue) {
return true;
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 26e9af027..055056887 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -171,6 +171,22 @@ bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info,
if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
cmSystemTools::ConvertToUnixSlashes(value);
}
+ } else if (key == "VS_17_DIR") {
+ // If generating for the VS 17 IDE, use the same instance.
+ cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
+ if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 17 ")) {
+ cmGlobalVisualStudioVersionedGenerator* vs17gen =
+ static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
+ if (vs17gen->GetVSInstance(value)) {
+ return true;
+ }
+ }
+
+ // Otherwise, find a VS 17 instance ourselves.
+ cmVSSetupAPIHelper vsSetupAPIHelper(17);
+ if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
+ cmSystemTools::ConvertToUnixSlashes(value);
+ }
#endif
} else {
std::string e = "does not recognize <key> " + key;
diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx
index 962fdcc9b..9a5fa7bfc 100644
--- a/Source/cmCMakePathCommand.cxx
+++ b/Source/cmCMakePathCommand.cxx
@@ -18,6 +18,7 @@
#include "cmCMakePath.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSubcommandTable.h"
@@ -149,8 +150,8 @@ public:
bool getInputPath(const std::string& arg, cmExecutionStatus& status,
std::string& path)
{
- const auto* def = status.GetMakefile().GetDefinition(arg);
- if (def == nullptr) {
+ cmProp def = status.GetMakefile().GetDefinition(arg);
+ if (!def) {
status.SetError("undefined variable for input path.");
return false;
}
diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx
index 16c2ed3d5..2f9972c38 100644
--- a/Source/cmCMakePresetsFile.cxx
+++ b/Source/cmCMakePresetsFile.cxx
@@ -9,28 +9,17 @@
#include <iterator>
#include <utility>
-#include <cmext/string_view>
+#include <cm/string_view>
-#include <cm3p/json/reader.h>
-#include <cm3p/json/value.h>
+#include "cmsys/RegularExpression.hxx"
-#include "cmsys/FStream.hxx"
-
-#include "cmJSONHelpers.h"
+#include "cmCMakePresetsFileInternal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmVersion.h"
-
-#define CHECK_OK(expr) \
- { \
- auto _result = expr; \
- if (_result != ReadFileResult::READ_OK) \
- return _result; \
- }
-#define CHECK_EXPAND(out, field, expanders) \
+#define CHECK_EXPAND(out, field, expanders, version) \
{ \
- switch (ExpandMacros(field, expanders)) { \
+ switch (ExpandMacros(field, expanders, version)) { \
case ExpandMacroResult::Error: \
return false; \
case ExpandMacroResult::Ignore: \
@@ -50,676 +39,11 @@ enum class CycleStatus
};
using ReadFileResult = cmCMakePresetsFile::ReadFileResult;
-using CacheVariable = cmCMakePresetsFile::CacheVariable;
using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset;
using BuildPreset = cmCMakePresetsFile::BuildPreset;
using TestPreset = cmCMakePresetsFile::TestPreset;
-using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy;
-
-constexpr int MIN_VERSION = 1;
-constexpr int MAX_VERSION = 2;
-
-struct CMakeVersion
-{
- unsigned int Major = 0;
- unsigned int Minor = 0;
- unsigned int Patch = 0;
-};
-
-struct RootPresets
-{
- CMakeVersion CMakeMinimumRequired;
- std::vector<cmCMakePresetsFile::ConfigurePreset> ConfigurePresets;
- std::vector<cmCMakePresetsFile::BuildPreset> BuildPresets;
- std::vector<cmCMakePresetsFile::TestPreset> TestPresets;
-};
-
-cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
-{
- return [error](std::nullptr_t& /*out*/,
- const Json::Value* value) -> ReadFileResult {
- if (!value) {
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isObject()) {
- return error;
- }
-
- return ReadFileResult::READ_OK;
- };
-}
-
-auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
-
-auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>(
- ReadFileResult::NO_VERSION, VersionIntHelper);
-
-auto const RootVersionHelper =
- cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_ROOT)
- .Bind("version"_s, VersionHelper, false);
-
-auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
-
-ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value)
-{
- if (!value) {
- out.clear();
- return ReadFileResult::READ_OK;
- }
-
- if (value->isBool()) {
- out = value->asBool() ? "TRUE" : "FALSE";
- return ReadFileResult::READ_OK;
- }
-
- return VariableStringHelper(out, value);
-}
-
-auto const VariableObjectHelper =
- cmJSONObjectHelper<CacheVariable, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false)
- .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false)
- .Bind("value"_s, &CacheVariable::Value, VariableValueHelper);
-
-ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
- const Json::Value* value)
-{
- if (value->isBool()) {
- out = CacheVariable{
- /*Type=*/"BOOL",
- /*Value=*/value->asBool() ? "TRUE" : "FALSE",
- };
- return ReadFileResult::READ_OK;
- }
- if (value->isString()) {
- out = CacheVariable{
- /*Type=*/"",
- /*Value=*/value->asString(),
- };
- return ReadFileResult::READ_OK;
- }
- if (value->isObject()) {
- out.emplace();
- return VariableObjectHelper(*out, value);
- }
- if (value->isNull()) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
- return ReadFileResult::INVALID_VARIABLE;
-}
-
-auto const VariablesHelper =
- cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
-
-auto const PresetStringHelper = cmJSONStringHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
-
-ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
- const Json::Value* value)
-{
- if (!value || value->isNull()) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
- if (value->isString()) {
- out = value->asString();
- return ReadFileResult::READ_OK;
- }
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const EnvironmentMapHelper =
- cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
- EnvironmentHelper);
-
-auto const PresetVectorStringHelper =
- cmJSONVectorHelper<std::string, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
- PresetStringHelper);
-
-ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out,
- const Json::Value* value)
-{
- out.clear();
- if (!value) {
- return ReadFileResult::READ_OK;
- }
-
- if (value->isString()) {
- out.push_back(value->asString());
- return ReadFileResult::READ_OK;
- }
-
- return PresetVectorStringHelper(out, value);
-}
-
-auto const PresetBoolHelper = cmJSONBoolHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
-
-auto const PresetOptionalBoolHelper =
- cmJSONOptionalHelper<bool, ReadFileResult>(ReadFileResult::READ_OK,
- PresetBoolHelper);
-
-auto const PresetIntHelper = cmJSONIntHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
-
-auto const PresetOptionalIntHelper = cmJSONOptionalHelper<int, ReadFileResult>(
- ReadFileResult::READ_OK, PresetIntHelper);
-
-auto const PresetVectorIntHelper = cmJSONVectorHelper<int, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper);
-
-auto const PresetWarningsHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false)
- .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated,
- PresetOptionalBoolHelper, false)
- .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized,
- PresetOptionalBoolHelper, false)
- .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli,
- PresetOptionalBoolHelper, false)
- .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars,
- PresetOptionalBoolHelper, false);
-
-auto const PresetErrorsHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false)
- .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated,
- PresetOptionalBoolHelper, false);
-
-auto const PresetDebugHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper,
- false)
- .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile,
- PresetOptionalBoolHelper, false)
- .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper,
- false);
-
-ReadFileResult ArchToolsetStrategyHelper(
- cm::optional<ArchToolsetStrategy>& out, const Json::Value* value)
-{
- if (!value) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "set") {
- out = ArchToolsetStrategy::Set;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "external") {
- out = ArchToolsetStrategy::External;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)>
-ArchToolsetHelper(
- std::string ConfigurePreset::*valueField,
- cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField)
-{
- auto const objectHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("value", valueField, PresetStringHelper, false)
- .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false);
- return [valueField, strategyField, objectHelper](
- ConfigurePreset& out, const Json::Value* value) -> ReadFileResult {
- if (!value) {
- (out.*valueField).clear();
- out.*strategyField = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (value->isString()) {
- out.*valueField = value->asString();
- out.*strategyField = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (value->isObject()) {
- return objectHelper(out, value);
- }
-
- return ReadFileResult::INVALID_PRESET;
- };
-}
-
-auto const ArchitectureHelper = ArchToolsetHelper(
- &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy);
-auto const ToolsetHelper = ArchToolsetHelper(
- &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy);
-
-auto const ConfigurePresetHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &ConfigurePreset::Inherits,
- PresetVectorOneOrMoreStringHelper, false)
- .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper,
- false)
- .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper,
- false)
- .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper,
- false)
- .Bind("architecture"_s, ArchitectureHelper, false)
- .Bind("toolset"_s, ToolsetHelper, false)
- .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper,
- false)
- .Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false)
- .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables,
- VariablesHelper, false)
- .Bind("environment"_s, &ConfigurePreset::Environment, EnvironmentMapHelper,
- false)
- .Bind("warnings"_s, PresetWarningsHelper, false)
- .Bind("errors"_s, PresetErrorsHelper, false)
- .Bind("debug"_s, PresetDebugHelper, false);
-
-auto const BuildPresetHelper =
- cmJSONObjectHelper<BuildPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &BuildPreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &BuildPreset::Inherits,
- PresetVectorOneOrMoreStringHelper, false)
- .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &BuildPreset::DisplayName, PresetStringHelper,
- false)
- .Bind("description"_s, &BuildPreset::Description, PresetStringHelper,
- false)
- .Bind("environment"_s, &BuildPreset::Environment, EnvironmentMapHelper,
- false)
- .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset,
- PresetStringHelper, false)
- .Bind("inheritConfigureEnvironment"_s,
- &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
- false)
- .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false)
- .Bind("targets"_s, &BuildPreset::Targets,
- PresetVectorOneOrMoreStringHelper, false)
- .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper,
- false)
- .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper,
- false)
- .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false)
- .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions,
- PresetVectorStringHelper, false);
-
-ReadFileResult TestPresetOutputVerbosityHelper(
- TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value)
-{
- if (!value) {
- out = TestPreset::OutputOptions::VerbosityEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "default") {
- out = TestPreset::OutputOptions::VerbosityEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "verbose") {
- out = TestPreset::OutputOptions::VerbosityEnum::Verbose;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "extra") {
- out = TestPreset::OutputOptions::VerbosityEnum::Extra;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalOutputVerbosityHelper =
- cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum,
- ReadFileResult>(ReadFileResult::READ_OK,
- TestPresetOutputVerbosityHelper);
-
-auto const TestPresetOptionalOutputHelper =
- cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress,
- PresetOptionalBoolHelper, false)
- .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity,
- TestPresetOptionalOutputVerbosityHelper, false)
- .Bind("debug"_s, &TestPreset::OutputOptions::Debug,
- PresetOptionalBoolHelper, false)
- .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure,
- PresetOptionalBoolHelper, false)
- .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet,
- PresetOptionalBoolHelper, false)
- .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile,
- PresetStringHelper, false)
- .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary,
- PresetOptionalBoolHelper, false)
- .Bind("subprojectSummary"_s,
- &TestPreset::OutputOptions::SubprojectSummary,
- PresetOptionalBoolHelper, false)
- .Bind("maxPassedTestOutputSize"_s,
- &TestPreset::OutputOptions::MaxPassedTestOutputSize,
- PresetOptionalIntHelper, false)
- .Bind("maxFailedTestOutputSize"_s,
- &TestPreset::OutputOptions::MaxFailedTestOutputSize,
- PresetOptionalIntHelper, false)
- .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth,
- PresetOptionalIntHelper, false));
-
-auto const TestPresetOptionalFilterIncludeIndexObjectHelper =
- cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions,
- ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_PRESET)
- .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start,
- PresetOptionalIntHelper, false)
- .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End,
- PresetOptionalIntHelper, false)
- .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride,
- PresetOptionalIntHelper, false)
- .Bind("specificTests"_s,
- &TestPreset::IncludeOptions::IndexOptions::SpecificTests,
- PresetVectorIntHelper, false));
-
-ReadFileResult TestPresetOptionalFilterIncludeIndexHelper(
- cm::optional<TestPreset::IncludeOptions::IndexOptions>& out,
- const Json::Value* value)
-{
- if (!value) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (value->isString()) {
- out.emplace();
- out->IndexFile = value->asString();
- return ReadFileResult::READ_OK;
- }
-
- if (value->isObject()) {
- return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value);
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalFilterIncludeHelper =
- cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("name"_s, &TestPreset::IncludeOptions::Name, PresetStringHelper,
- false)
- .Bind("label"_s, &TestPreset::IncludeOptions::Label, PresetStringHelper,
- false)
- .Bind("index"_s, &TestPreset::IncludeOptions::Index,
- TestPresetOptionalFilterIncludeIndexHelper, false)
- .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion,
- PresetOptionalBoolHelper, false));
-
-auto const TestPresetOptionalFilterExcludeFixturesHelper =
- cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions,
- ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_PRESET)
- .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any,
- PresetStringHelper, false)
- .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup,
- PresetStringHelper, false)
- .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup,
- PresetStringHelper, false));
-
-auto const TestPresetOptionalFilterExcludeHelper =
- cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("name"_s, &TestPreset::ExcludeOptions::Name, PresetStringHelper,
- false)
- .Bind("label"_s, &TestPreset::ExcludeOptions::Label, PresetStringHelper,
- false)
- .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures,
- TestPresetOptionalFilterExcludeFixturesHelper, false));
-
-ReadFileResult TestPresetExecutionShowOnlyHelper(
- TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value)
-{
- if (!value || !value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "human") {
- out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "json-v1") {
- out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalExecutionShowOnlyHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum,
- ReadFileResult>(ReadFileResult::READ_OK,
- TestPresetExecutionShowOnlyHelper);
-
-ReadFileResult TestPresetExecutionModeHelper(
- TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out,
- const Json::Value* value)
-{
- if (!value) {
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "until-fail") {
- out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "until-pass") {
- out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "after-timeout") {
- out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalExecutionRepeatHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions,
- ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_PRESET)
- .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode,
- TestPresetExecutionModeHelper, true)
- .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count,
- PresetIntHelper, true));
-
-ReadFileResult TestPresetExecutionNoTestsActionHelper(
- TestPreset::ExecutionOptions::NoTestsActionEnum& out,
- const Json::Value* value)
-{
- if (!value) {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "default") {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "error") {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "ignore") {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalExecutionNoTestsActionHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum,
- ReadFileResult>(ReadFileResult::READ_OK,
- TestPresetExecutionNoTestsActionHelper);
-
-auto const TestPresetExecutionHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure,
- PresetOptionalBoolHelper, false)
- .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover,
- PresetOptionalBoolHelper, false)
- .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs,
- PresetOptionalIntHelper, false)
- .Bind("resourceSpecFile"_s,
- &TestPreset::ExecutionOptions::ResourceSpecFile,
- PresetStringHelper, false)
- .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad,
- PresetOptionalIntHelper, false)
- .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly,
- TestPresetOptionalExecutionShowOnlyHelper, false)
- .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat,
- TestPresetOptionalExecutionRepeatHelper, false)
- .Bind("interactiveDebugging"_s,
- &TestPreset::ExecutionOptions::InteractiveDebugging,
- PresetOptionalBoolHelper, false)
- .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom,
- PresetOptionalBoolHelper, false)
- .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout,
- PresetOptionalIntHelper, false)
- .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction,
- TestPresetOptionalExecutionNoTestsActionHelper, false));
-
-auto const TestPresetFilterHelper =
- cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("include"_s, &TestPreset::FilterOptions::Include,
- TestPresetOptionalFilterIncludeHelper, false)
- .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude,
- TestPresetOptionalFilterExcludeHelper, false));
-
-auto const TestPresetHelper =
- cmJSONObjectHelper<TestPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &TestPreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &TestPreset::Inherits,
- PresetVectorOneOrMoreStringHelper, false)
- .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &TestPreset::DisplayName, PresetStringHelper, false)
- .Bind("description"_s, &TestPreset::Description, PresetStringHelper, false)
- .Bind("environment"_s, &TestPreset::Environment, EnvironmentMapHelper,
- false)
- .Bind("configurePreset"_s, &TestPreset::ConfigurePreset,
- PresetStringHelper, false)
- .Bind("inheritConfigureEnvironment"_s,
- &TestPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
- false)
- .Bind("configuration"_s, &TestPreset::Configuration, PresetStringHelper,
- false)
- .Bind("overwriteConfigurationFile"_s,
- &TestPreset::OverwriteConfigurationFile, PresetVectorStringHelper,
- false)
- .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper,
- false)
- .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false)
- .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper,
- false);
-
-auto const ConfigurePresetsHelper =
- cmJSONVectorHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
- ConfigurePresetHelper);
-
-auto const BuildPresetsHelper =
- cmJSONVectorHelper<BuildPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
- BuildPresetHelper);
-
-auto const TestPresetsHelper = cmJSONVectorHelper<TestPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper);
-
-auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
-
-auto const CMakeVersionHelper =
- cmJSONObjectHelper<CMakeVersion, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
- .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
- .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
- .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);
-
-auto const RootPresetsHelper =
- cmJSONObjectHelper<RootPresets, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
- .Bind<int>("version"_s, nullptr, VersionHelper)
- .Bind("configurePresets"_s, &RootPresets::ConfigurePresets,
- ConfigurePresetsHelper, false)
- .Bind("buildPresets"_s, &RootPresets::BuildPresets, BuildPresetsHelper,
- false)
- .Bind("testPresets"_s, &RootPresets::TestPresets, TestPresetsHelper, false)
- .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
- CMakeVersionHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_ROOT), false);
+using ExpandMacroResult = cmCMakePresetsFileInternal::ExpandMacroResult;
+using MacroExpander = cmCMakePresetsFileInternal::MacroExpander;
void InheritString(std::string& child, const std::string& parent)
{
@@ -754,7 +78,7 @@ void InheritVector(std::vector<T>& child, const std::vector<T>& parent)
template <class T>
ReadFileResult VisitPreset(
T& preset, std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets,
- std::map<std::string, CycleStatus> cycleStatus)
+ std::map<std::string, CycleStatus> cycleStatus, int version)
{
switch (cycleStatus[preset.Name]) {
case CycleStatus::InProgress:
@@ -784,7 +108,7 @@ ReadFileResult VisitPreset(
return ReadFileResult::USER_PRESET_INHERITANCE;
}
- auto result = VisitPreset(parentPreset, presets, cycleStatus);
+ auto result = VisitPreset(parentPreset, presets, cycleStatus, version);
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -794,9 +118,17 @@ ReadFileResult VisitPreset(
for (auto const& v : parentPreset.Environment) {
preset.Environment.insert(v);
}
+
+ if (!preset.ConditionEvaluator) {
+ preset.ConditionEvaluator = parentPreset.ConditionEvaluator;
+ }
}
- CHECK_OK(preset.VisitPresetAfterInherit())
+ if (preset.ConditionEvaluator && preset.ConditionEvaluator->IsNull()) {
+ preset.ConditionEvaluator.reset();
+ }
+
+ CHECK_OK(preset.VisitPresetAfterInherit(version))
cycleStatus[preset.Name] = CycleStatus::Verified;
return ReadFileResult::READ_OK;
@@ -804,7 +136,8 @@ ReadFileResult VisitPreset(
template <class T>
ReadFileResult ComputePresetInheritance(
- std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets)
+ std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets,
+ const cmCMakePresetsFile& file)
{
std::map<std::string, CycleStatus> cycleStatus;
for (auto const& it : presets) {
@@ -812,7 +145,9 @@ ReadFileResult ComputePresetInheritance(
}
for (auto& it : presets) {
- auto result = VisitPreset<T>(it.second.Unexpanded, presets, cycleStatus);
+ auto& preset = it.second.Unexpanded;
+ auto result =
+ VisitPreset<T>(preset, presets, cycleStatus, file.GetVersion(preset));
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -842,24 +177,17 @@ bool IsValidMacroNamespace(const std::string& str)
[&str](const char* prefix) -> bool { return str == prefix; });
}
-enum class ExpandMacroResult
-{
- Ok,
- Ignore,
- Error,
-};
-
-using MacroExpander = std::function<ExpandMacroResult(
- const std::string&, const std::string&, std::string&)>;
-
ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
- const std::vector<MacroExpander>& macroExpanders);
+ const std::vector<MacroExpander>& macroExpanders,
+ int version);
ExpandMacroResult ExpandMacros(
- std::string& out, const std::vector<MacroExpander>& macroExpanders);
-ExpandMacroResult ExpandMacro(
- std::string& out, const std::string& macroNamespace,
- const std::string& macroName,
- const std::vector<MacroExpander>& macroExpanders);
+ std::string& out, const std::vector<MacroExpander>& macroExpanders,
+ int version);
+ExpandMacroResult ExpandMacro(std::string& out,
+ const std::string& macroNamespace,
+ const std::string& macroName,
+ const std::vector<MacroExpander>& macroExpanders,
+ int version);
bool ExpandMacros(const cmCMakePresetsFile& file,
const ConfigurePreset& preset,
@@ -867,7 +195,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file,
const std::vector<MacroExpander>& macroExpanders)
{
std::string binaryDir = preset.BinaryDir;
- CHECK_EXPAND(out, binaryDir, macroExpanders)
+ CHECK_EXPAND(out, binaryDir, macroExpanders, file.GetVersion(preset))
if (!cmSystemTools::FileIsFullPath(binaryDir)) {
binaryDir = cmStrCat(file.SourceDir, '/', binaryDir);
@@ -875,69 +203,95 @@ bool ExpandMacros(const cmCMakePresetsFile& file,
out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
+ if (!preset.InstallDir.empty()) {
+ std::string installDir = preset.InstallDir;
+ CHECK_EXPAND(out, installDir, macroExpanders, file.GetVersion(preset))
+
+ if (!cmSystemTools::FileIsFullPath(installDir)) {
+ installDir = cmStrCat(file.SourceDir, '/', installDir);
+ }
+ out->InstallDir = cmSystemTools::CollapseFullPath(installDir);
+ cmSystemTools::ConvertToUnixSlashes(out->InstallDir);
+ }
+
+ if (!preset.ToolchainFile.empty()) {
+ std::string toolchain = preset.ToolchainFile;
+ CHECK_EXPAND(out, toolchain, macroExpanders, file.GetVersion(preset))
+ out->ToolchainFile = toolchain;
+ }
+
for (auto& variable : out->CacheVariables) {
if (variable.second) {
- CHECK_EXPAND(out, variable.second->Value, macroExpanders)
+ CHECK_EXPAND(out, variable.second->Value, macroExpanders,
+ file.GetVersion(preset))
}
}
return true;
}
-bool ExpandMacros(const cmCMakePresetsFile&, const BuildPreset&,
+bool ExpandMacros(const cmCMakePresetsFile& file, const BuildPreset& preset,
cm::optional<BuildPreset>& out,
const std::vector<MacroExpander>& macroExpanders)
{
for (auto& target : out->Targets) {
- CHECK_EXPAND(out, target, macroExpanders)
+ CHECK_EXPAND(out, target, macroExpanders, file.GetVersion(preset))
}
for (auto& nativeToolOption : out->NativeToolOptions) {
- CHECK_EXPAND(out, nativeToolOption, macroExpanders)
+ CHECK_EXPAND(out, nativeToolOption, macroExpanders,
+ file.GetVersion(preset))
}
return true;
}
-bool ExpandMacros(const cmCMakePresetsFile&, const TestPreset&,
+bool ExpandMacros(const cmCMakePresetsFile& file, const TestPreset& preset,
cm::optional<TestPreset>& out,
const std::vector<MacroExpander>& macroExpanders)
{
for (auto& overwrite : out->OverwriteConfigurationFile) {
- CHECK_EXPAND(out, overwrite, macroExpanders);
+ CHECK_EXPAND(out, overwrite, macroExpanders, file.GetVersion(preset));
}
if (out->Output) {
- CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders)
+ CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders,
+ file.GetVersion(preset))
}
if (out->Filter) {
if (out->Filter->Include) {
- CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders)
- CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders,
+ file.GetVersion(preset))
+ CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders,
+ file.GetVersion(preset))
if (out->Filter->Include->Index) {
CHECK_EXPAND(out, out->Filter->Include->Index->IndexFile,
- macroExpanders);
+ macroExpanders, file.GetVersion(preset));
}
}
if (out->Filter->Exclude) {
- CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders)
- CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders,
+ file.GetVersion(preset))
+ CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders,
+ file.GetVersion(preset))
if (out->Filter->Exclude->Fixtures) {
- CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders,
+ file.GetVersion(preset))
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Setup,
- macroExpanders)
+ macroExpanders, file.GetVersion(preset))
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Cleanup,
- macroExpanders)
+ macroExpanders, file.GetVersion(preset))
}
}
}
if (out->Execution) {
- CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders)
+ CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders,
+ file.GetVersion(preset))
}
return true;
@@ -958,8 +312,8 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
MacroExpander defaultMacroExpander =
[&file, &preset](const std::string& macroNamespace,
- const std::string& macroName,
- std::string& macroOut) -> ExpandMacroResult {
+ const std::string& macroName, std::string& macroOut,
+ int version) -> ExpandMacroResult {
if (macroNamespace.empty()) {
if (macroName == "sourceDir") {
macroOut += file.SourceDir;
@@ -988,6 +342,13 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
macroOut += '$';
return ExpandMacroResult::Ok;
}
+ if (macroName == "hostSystemName") {
+ if (version < 3) {
+ return ExpandMacroResult::Error;
+ }
+ macroOut += cmSystemTools::GetSystemName();
+ return ExpandMacroResult::Ok;
+ }
}
return ExpandMacroResult::Ignore;
@@ -996,11 +357,12 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
MacroExpander environmentMacroExpander =
[&macroExpanders, &out, &envCycles](
const std::string& macroNamespace, const std::string& macroName,
- std::string& result) -> ExpandMacroResult {
+ std::string& result, int version) -> ExpandMacroResult {
if (macroNamespace == "env" && !macroName.empty() && out) {
auto v = out->Environment.find(macroName);
if (v != out->Environment.end() && v->second) {
- auto e = VisitEnv(*v->second, envCycles[macroName], macroExpanders);
+ auto e =
+ VisitEnv(*v->second, envCycles[macroName], macroExpanders, version);
if (e != ExpandMacroResult::Ok) {
return e;
}
@@ -1028,7 +390,8 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
for (auto& v : out->Environment) {
if (v.second) {
- switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders)) {
+ switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders,
+ file.GetVersion(preset))) {
case ExpandMacroResult::Error:
return false;
case ExpandMacroResult::Ignore:
@@ -1040,11 +403,25 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
}
}
+ if (preset.ConditionEvaluator) {
+ cm::optional<bool> result;
+ if (!preset.ConditionEvaluator->Evaluate(
+ macroExpanders, file.GetVersion(preset), result)) {
+ return false;
+ }
+ if (!result) {
+ out.reset();
+ return true;
+ }
+ out->ConditionResult = *result;
+ }
+
return ExpandMacros(file, preset, out, macroExpanders);
}
ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
- const std::vector<MacroExpander>& macroExpanders)
+ const std::vector<MacroExpander>& macroExpanders,
+ int version)
{
if (status == CycleStatus::Verified) {
return ExpandMacroResult::Ok;
@@ -1054,7 +431,7 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
}
status = CycleStatus::InProgress;
- auto e = ExpandMacros(value, macroExpanders);
+ auto e = ExpandMacros(value, macroExpanders, version);
if (e != ExpandMacroResult::Ok) {
return e;
}
@@ -1063,7 +440,8 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
}
ExpandMacroResult ExpandMacros(
- std::string& out, const std::vector<MacroExpander>& macroExpanders)
+ std::string& out, const std::vector<MacroExpander>& macroExpanders,
+ int version)
{
std::string result;
std::string macroNamespace;
@@ -1110,8 +488,8 @@ ExpandMacroResult ExpandMacros(
case State::MacroName:
if (c == '}') {
- auto e =
- ExpandMacro(result, macroNamespace, macroName, macroExpanders);
+ auto e = ExpandMacro(result, macroNamespace, macroName,
+ macroExpanders, version);
if (e != ExpandMacroResult::Ok) {
return e;
}
@@ -1143,10 +521,11 @@ ExpandMacroResult ExpandMacros(
ExpandMacroResult ExpandMacro(std::string& out,
const std::string& macroNamespace,
const std::string& macroName,
- const std::vector<MacroExpander>& macroExpanders)
+ const std::vector<MacroExpander>& macroExpanders,
+ int version)
{
for (auto const& macroExpander : macroExpanders) {
- auto result = macroExpander(macroNamespace, macroName, out);
+ auto result = macroExpander(macroNamespace, macroName, out, version);
if (result != ExpandMacroResult::Ignore) {
return result;
}
@@ -1160,6 +539,98 @@ ExpandMacroResult ExpandMacro(std::string& out,
}
}
+bool cmCMakePresetsFileInternal::EqualsCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ std::string lhs = this->Lhs;
+ CHECK_EXPAND(out, lhs, expanders, version);
+
+ std::string rhs = this->Rhs;
+ CHECK_EXPAND(out, rhs, expanders, version);
+
+ out = (lhs == rhs);
+ return true;
+}
+
+bool cmCMakePresetsFileInternal::InListCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ std::string str = this->String;
+ CHECK_EXPAND(out, str, expanders, version);
+
+ for (auto item : this->List) {
+ CHECK_EXPAND(out, item, expanders, version);
+ if (str == item) {
+ out = true;
+ return true;
+ }
+ }
+
+ out = false;
+ return true;
+}
+
+bool cmCMakePresetsFileInternal::MatchesCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ std::string str = this->String;
+ CHECK_EXPAND(out, str, expanders, version);
+ std::string regexStr = this->Regex;
+ CHECK_EXPAND(out, regexStr, expanders, version);
+
+ cmsys::RegularExpression regex;
+ if (!regex.compile(regexStr)) {
+ return false;
+ }
+
+ out = regex.find(str);
+ return true;
+}
+
+bool cmCMakePresetsFileInternal::AnyAllOfCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ for (auto const& condition : this->Conditions) {
+ cm::optional<bool> result;
+ if (!condition->Evaluate(expanders, version, result)) {
+ out.reset();
+ return false;
+ }
+
+ if (!result) {
+ out.reset();
+ return true;
+ }
+
+ if (result == this->StopValue) {
+ out = result;
+ return true;
+ }
+ }
+
+ out = !this->StopValue;
+ return true;
+}
+
+bool cmCMakePresetsFileInternal::NotCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ out.reset();
+ if (!this->SubCondition->Evaluate(expanders, version, out)) {
+ out.reset();
+ return false;
+ }
+ if (out) {
+ *out = !*out;
+ }
+ return true;
+}
+
cmCMakePresetsFile::ReadFileResult
cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit(
const cmCMakePresetsFile::Preset& parentPreset)
@@ -1177,6 +648,8 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit(
preset.ToolsetStrategy = parent.ToolsetStrategy;
}
InheritString(preset.BinaryDir, parent.BinaryDir);
+ InheritString(preset.InstallDir, parent.InstallDir);
+ InheritString(preset.ToolchainFile, parent.ToolchainFile);
InheritOptionalValue(preset.WarnDev, parent.WarnDev);
InheritOptionalValue(preset.ErrorDev, parent.ErrorDev);
InheritOptionalValue(preset.WarnDeprecated, parent.WarnDeprecated);
@@ -1204,16 +677,19 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetBeforeInherit()
}
cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit()
+cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit(int version)
{
auto& preset = *this;
if (!preset.Hidden) {
- if (preset.Generator.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
- if (preset.BinaryDir.empty()) {
- return ReadFileResult::INVALID_PRESET;
+ if (version < 3) {
+ if (preset.Generator.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ if (preset.BinaryDir.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
}
+
if (preset.WarnDev == false && preset.ErrorDev == true) {
return ReadFileResult::INVALID_PRESET;
}
@@ -1249,7 +725,7 @@ cmCMakePresetsFile::BuildPreset::VisitPresetInherit(
}
cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit()
+cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit(int /* version */)
{
auto& preset = *this;
if (!preset.Hidden && preset.ConfigurePreset.empty()) {
@@ -1359,7 +835,7 @@ cmCMakePresetsFile::TestPreset::VisitPresetInherit(
}
cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit()
+cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit(int /* version */)
{
auto& preset = *this;
if (!preset.Hidden && preset.ConfigurePreset.empty()) {
@@ -1420,9 +896,9 @@ cmCMakePresetsFile::ReadProjectPresetsInternal(bool allowNoFiles)
: ReadFileResult::FILE_NOT_FOUND;
}
- CHECK_OK(ComputePresetInheritance(this->ConfigurePresets))
- CHECK_OK(ComputePresetInheritance(this->BuildPresets))
- CHECK_OK(ComputePresetInheritance(this->TestPresets))
+ CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this))
+ CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this))
+ CHECK_OK(ComputePresetInheritance(this->TestPresets, *this))
for (auto& it : this->ConfigurePresets) {
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
@@ -1513,111 +989,21 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result)
"support.";
case ReadFileResult::INVALID_CONFIGURE_PRESET:
return "Invalid \"configurePreset\" field";
+ case ReadFileResult::INSTALL_PREFIX_UNSUPPORTED:
+ return "File version must be 3 or higher for installDir preset "
+ "support.";
+ case ReadFileResult::INVALID_CONDITION:
+ return "Invalid preset condition";
+ case ReadFileResult::CONDITION_UNSUPPORTED:
+ return "File version must be 3 or higher for condition support";
+ case ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED:
+ return "File version must be 3 or higher for toolchainFile preset "
+ "support.";
}
return "Unknown error";
}
-cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
- const std::string& filename, bool user)
-{
- cmsys::ifstream fin(filename.c_str());
- if (!fin) {
- return ReadFileResult::FILE_NOT_FOUND;
- }
- // If there's a BOM, toss it.
- cmsys::FStream::ReadBOM(fin);
-
- Json::Value root;
- Json::CharReaderBuilder builder;
- Json::CharReaderBuilder::strictMode(&builder.settings_);
- if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
- return ReadFileResult::JSON_PARSE_ERROR;
- }
-
- int v = 0;
- auto result = RootVersionHelper(v, &root);
- if (result != ReadFileResult::READ_OK) {
- return result;
- }
- if (v < MIN_VERSION || v > MAX_VERSION) {
- return ReadFileResult::UNRECOGNIZED_VERSION;
- }
-
- // Support for build and test presets added in version 2.
- if (v < 2 &&
- (root.isMember("buildPresets") || root.isMember("testPresets"))) {
- return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
- }
-
- RootPresets presets;
- if ((result = RootPresetsHelper(presets, &root)) !=
- ReadFileResult::READ_OK) {
- return result;
- }
-
- unsigned int currentMajor = cmVersion::GetMajorVersion();
- unsigned int currentMinor = cmVersion::GetMinorVersion();
- unsigned int currentPatch = cmVersion::GetPatchVersion();
- auto const& required = presets.CMakeMinimumRequired;
- if (required.Major > currentMajor ||
- (required.Major == currentMajor &&
- (required.Minor > currentMinor ||
- (required.Minor == currentMinor &&
- (required.Patch > currentPatch))))) {
- return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
- }
-
- for (auto& preset : presets.ConfigurePresets) {
- preset.User = user;
- if (preset.Name.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- PresetPair<ConfigurePreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->ConfigurePresets
- .emplace(std::make_pair(preset.Name, presetPair))
- .second) {
- return ReadFileResult::DUPLICATE_PRESETS;
- }
- this->ConfigurePresetOrder.push_back(preset.Name);
- }
-
- for (auto& preset : presets.BuildPresets) {
- preset.User = user;
- if (preset.Name.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- PresetPair<BuildPreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
- return ReadFileResult::DUPLICATE_PRESETS;
- }
- this->BuildPresetOrder.push_back(preset.Name);
- }
-
- for (auto& preset : presets.TestPresets) {
- preset.User = user;
- if (preset.Name.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- PresetPair<TestPreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
- return ReadFileResult::DUPLICATE_PRESETS;
- }
- this->TestPresetOrder.push_back(preset.Name);
- }
-
- return ReadFileResult::READ_OK;
-}
-
void cmCMakePresetsFile::ClearPresets()
{
this->ConfigurePresets.clear();
@@ -1669,7 +1055,7 @@ void cmCMakePresetsFile::PrintConfigurePresetList(
for (auto const& p : this->ConfigurePresetOrder) {
auto const& preset = this->ConfigurePresets.at(p);
if (!preset.Unexpanded.Hidden && preset.Expanded &&
- filter(preset.Unexpanded)) {
+ preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
presets.push_back(
static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
}
@@ -1686,7 +1072,8 @@ void cmCMakePresetsFile::PrintBuildPresetList() const
std::vector<const cmCMakePresetsFile::Preset*> presets;
for (auto const& p : this->BuildPresetOrder) {
auto const& preset = this->BuildPresets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded) {
+ if (!preset.Unexpanded.Hidden && preset.Expanded &&
+ preset.Expanded->ConditionResult) {
presets.push_back(
static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
}
@@ -1703,7 +1090,8 @@ void cmCMakePresetsFile::PrintTestPresetList() const
std::vector<const cmCMakePresetsFile::Preset*> presets;
for (auto const& p : this->TestPresetOrder) {
auto const& preset = this->TestPresets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded) {
+ if (!preset.Unexpanded.Hidden && preset.Expanded &&
+ preset.Expanded->ConditionResult) {
presets.push_back(
static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
}
diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h
index 3067d5e07..7aa9b6acc 100644
--- a/Source/cmCMakePresetsFile.h
+++ b/Source/cmCMakePresetsFile.h
@@ -2,8 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
#include <functional>
#include <map>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -33,6 +36,10 @@ public:
INVALID_MACRO_EXPANSION,
BUILD_TEST_PRESETS_UNSUPPORTED,
INVALID_CONFIGURE_PRESET,
+ INSTALL_PREFIX_UNSUPPORTED,
+ INVALID_CONDITION,
+ CONDITION_UNSUPPORTED,
+ TOOLCHAIN_FILE_UNSUPPORTED,
};
enum class ArchToolsetStrategy
@@ -48,6 +55,8 @@ public:
std::string Value;
};
+ class Condition;
+
class Preset
{
public:
@@ -70,6 +79,9 @@ public:
std::string DisplayName;
std::string Description;
+ std::shared_ptr<Condition> ConditionEvaluator;
+ bool ConditionResult = true;
+
std::map<std::string, cm::optional<std::string>> Environment;
virtual ReadFileResult VisitPresetInherit(const Preset& parent) = 0;
@@ -78,7 +90,7 @@ public:
return ReadFileResult::READ_OK;
}
- virtual ReadFileResult VisitPresetAfterInherit()
+ virtual ReadFileResult VisitPresetAfterInherit(int /* version */)
{
return ReadFileResult::READ_OK;
}
@@ -102,7 +114,9 @@ public:
cm::optional<ArchToolsetStrategy> ArchitectureStrategy;
std::string Toolset;
cm::optional<ArchToolsetStrategy> ToolsetStrategy;
+ std::string ToolchainFile;
std::string BinaryDir;
+ std::string InstallDir;
std::map<std::string, cm::optional<CacheVariable>> CacheVariables;
@@ -120,7 +134,7 @@ public:
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetBeforeInherit() override;
- ReadFileResult VisitPresetAfterInherit() override;
+ ReadFileResult VisitPresetAfterInherit(int version) override;
};
class BuildPreset : public Preset
@@ -146,7 +160,7 @@ public:
std::vector<std::string> NativeToolOptions;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
- ReadFileResult VisitPresetAfterInherit() override;
+ ReadFileResult VisitPresetAfterInherit(int /* version */) override;
};
class TestPreset : public Preset
@@ -273,7 +287,7 @@ public:
cm::optional<ExecutionOptions> Execution;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
- ReadFileResult VisitPresetAfterInherit() override;
+ ReadFileResult VisitPresetAfterInherit(int /* version */) override;
};
template <class T>
@@ -293,6 +307,13 @@ public:
std::vector<std::string> TestPresetOrder;
std::string SourceDir;
+ int Version;
+ int UserVersion;
+
+ int GetVersion(const Preset& preset) const
+ {
+ return preset.User ? this->UserVersion : this->Version;
+ }
static std::string GetFilename(const std::string& sourceDir);
static std::string GetUserFilename(const std::string& sourceDir);
diff --git a/Source/cmCMakePresetsFileInternal.h b/Source/cmCMakePresetsFileInternal.h
new file mode 100644
index 000000000..326927612
--- /dev/null
+++ b/Source/cmCMakePresetsFileInternal.h
@@ -0,0 +1,112 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <memory>
+
+#include "cmCMakePresetsFile.h"
+
+#define CHECK_OK(expr) \
+ { \
+ auto _result = expr; \
+ if (_result != ReadFileResult::READ_OK) \
+ return _result; \
+ }
+
+namespace cmCMakePresetsFileInternal {
+enum class ExpandMacroResult
+{
+ Ok,
+ Ignore,
+ Error,
+};
+
+using MacroExpander = std::function<ExpandMacroResult(
+ const std::string&, const std::string&, std::string&, int version)>;
+}
+
+class cmCMakePresetsFile::Condition
+{
+public:
+ virtual ~Condition() = default;
+
+ virtual bool Evaluate(
+ const std::vector<cmCMakePresetsFileInternal::MacroExpander>& expanders,
+ int version, cm::optional<bool>& out) const = 0;
+ virtual bool IsNull() const { return false; }
+};
+
+namespace cmCMakePresetsFileInternal {
+
+class NullCondition : public cmCMakePresetsFile::Condition
+{
+ bool Evaluate(const std::vector<MacroExpander>& /*expanders*/,
+ int /*version*/, cm::optional<bool>& out) const override
+ {
+ out = true;
+ return true;
+ }
+
+ bool IsNull() const override { return true; }
+};
+
+class ConstCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& /*expanders*/,
+ int /*version*/, cm::optional<bool>& out) const override
+ {
+ out = this->Value;
+ return true;
+ }
+
+ bool Value;
+};
+
+class EqualsCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::string Lhs;
+ std::string Rhs;
+};
+
+class InListCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::string String;
+ std::vector<std::string> List;
+};
+
+class MatchesCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::string String;
+ std::string Regex;
+};
+
+class AnyAllOfCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::vector<std::unique_ptr<Condition>> Conditions;
+ bool StopValue;
+};
+
+class NotCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::unique_ptr<Condition> SubCondition;
+};
+}
diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx
new file mode 100644
index 000000000..489551dcf
--- /dev/null
+++ b/Source/cmCMakePresetsFileReadJSON.cxx
@@ -0,0 +1,1032 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <functional>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include <cm3p/json/reader.h>
+#include <cm3p/json/value.h>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmCMakePresetsFile.h"
+#include "cmCMakePresetsFileInternal.h"
+#include "cmJSONHelpers.h"
+#include "cmVersion.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsFile::ReadFileResult;
+using CacheVariable = cmCMakePresetsFile::CacheVariable;
+using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset;
+using BuildPreset = cmCMakePresetsFile::BuildPreset;
+using TestPreset = cmCMakePresetsFile::TestPreset;
+using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy;
+
+constexpr int MIN_VERSION = 1;
+constexpr int MAX_VERSION = 3;
+
+struct CMakeVersion
+{
+ unsigned int Major = 0;
+ unsigned int Minor = 0;
+ unsigned int Patch = 0;
+};
+
+struct RootPresets
+{
+ CMakeVersion CMakeMinimumRequired;
+ std::vector<cmCMakePresetsFile::ConfigurePreset> ConfigurePresets;
+ std::vector<cmCMakePresetsFile::BuildPreset> BuildPresets;
+ std::vector<cmCMakePresetsFile::TestPreset> TestPresets;
+};
+
+std::unique_ptr<cmCMakePresetsFileInternal::NotCondition> InvertCondition(
+ std::unique_ptr<cmCMakePresetsFile::Condition> condition)
+{
+ auto retval = cm::make_unique<cmCMakePresetsFileInternal::NotCondition>();
+ retval->SubCondition = std::move(condition);
+ return retval;
+}
+
+auto const ConditionStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
+
+auto const ConditionBoolHelper = cmJSONBoolHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
+
+auto const ConditionStringListHelper =
+ cmJSONVectorHelper<std::string, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION,
+ ConditionStringHelper);
+
+auto const ConstConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::ConstCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("value"_s, &cmCMakePresetsFileInternal::ConstCondition::Value,
+ ConditionBoolHelper, true);
+
+auto const EqualsConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::EqualsCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("lhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Lhs,
+ ConditionStringHelper, true)
+ .Bind("rhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Rhs,
+ ConditionStringHelper, true);
+
+auto const InListConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::InListCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("string"_s, &cmCMakePresetsFileInternal::InListCondition::String,
+ ConditionStringHelper, true)
+ .Bind("list"_s, &cmCMakePresetsFileInternal::InListCondition::List,
+ ConditionStringListHelper, true);
+
+auto const MatchesConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::MatchesCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("string"_s, &cmCMakePresetsFileInternal::MatchesCondition::String,
+ ConditionStringHelper, true)
+ .Bind("regex"_s, &cmCMakePresetsFileInternal::MatchesCondition::Regex,
+ ConditionStringHelper, true);
+
+ReadFileResult SubConditionHelper(
+ std::unique_ptr<cmCMakePresetsFile::Condition>& out,
+ const Json::Value* value);
+
+auto const ListConditionVectorHelper =
+ cmJSONVectorHelper<std::unique_ptr<cmCMakePresetsFile::Condition>,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION,
+ SubConditionHelper);
+auto const AnyAllOfConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::AnyAllOfCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("conditions"_s,
+ &cmCMakePresetsFileInternal::AnyAllOfCondition::Conditions,
+ ListConditionVectorHelper);
+
+auto const NotConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::NotCondition, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("condition"_s,
+ &cmCMakePresetsFileInternal::NotCondition::SubCondition,
+ SubConditionHelper);
+
+ReadFileResult ConditionHelper(
+ std::unique_ptr<cmCMakePresetsFile::Condition>& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out.reset();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isBool()) {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::ConstCondition>();
+ c->Value = value->asBool();
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isNull()) {
+ out = cm::make_unique<cmCMakePresetsFileInternal::NullCondition>();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isObject()) {
+ if (!value->isMember("type")) {
+ return ReadFileResult::INVALID_CONDITION;
+ }
+
+ if (!(*value)["type"].isString()) {
+ return ReadFileResult::INVALID_CONDITION;
+ }
+ auto type = (*value)["type"].asString();
+
+ if (type == "const") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::ConstCondition>();
+ CHECK_OK(ConstConditionHelper(*c, value));
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "equals" || type == "notEquals") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::EqualsCondition>();
+ CHECK_OK(EqualsConditionHelper(*c, value));
+ out = std::move(c);
+ if (type == "notEquals") {
+ out = InvertCondition(std::move(out));
+ }
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "inList" || type == "notInList") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::InListCondition>();
+ CHECK_OK(InListConditionHelper(*c, value));
+ out = std::move(c);
+ if (type == "notInList") {
+ out = InvertCondition(std::move(out));
+ }
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "matches" || type == "notMatches") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::MatchesCondition>();
+ CHECK_OK(MatchesConditionHelper(*c, value));
+ out = std::move(c);
+ if (type == "notMatches") {
+ out = InvertCondition(std::move(out));
+ }
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "anyOf" || type == "allOf") {
+ auto c =
+ cm::make_unique<cmCMakePresetsFileInternal::AnyAllOfCondition>();
+ c->StopValue = (type == "anyOf");
+ CHECK_OK(AnyAllOfConditionHelper(*c, value));
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "not") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::NotCondition>();
+ CHECK_OK(NotConditionHelper(*c, value));
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+ }
+
+ return ReadFileResult::INVALID_CONDITION;
+}
+
+ReadFileResult PresetConditionHelper(
+ std::shared_ptr<cmCMakePresetsFile::Condition>& out,
+ const Json::Value* value)
+{
+ std::unique_ptr<cmCMakePresetsFile::Condition> ptr;
+ auto result = ConditionHelper(ptr, value);
+ out = std::move(ptr);
+ return result;
+}
+
+ReadFileResult SubConditionHelper(
+ std::unique_ptr<cmCMakePresetsFile::Condition>& out,
+ const Json::Value* value)
+{
+ std::unique_ptr<cmCMakePresetsFile::Condition> ptr;
+ auto result = ConditionHelper(ptr, value);
+ if (ptr && ptr->IsNull()) {
+ return ReadFileResult::INVALID_CONDITION;
+ }
+ out = std::move(ptr);
+ return result;
+}
+
+cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
+{
+ return [error](std::nullptr_t& /*out*/,
+ const Json::Value* value) -> ReadFileResult {
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isObject()) {
+ return error;
+ }
+
+ return ReadFileResult::READ_OK;
+ };
+}
+
+auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
+
+auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>(
+ ReadFileResult::NO_VERSION, VersionIntHelper);
+
+auto const RootVersionHelper =
+ cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_ROOT)
+ .Bind("version"_s, VersionHelper, false);
+
+auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
+
+ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value)
+{
+ if (!value) {
+ out.clear();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isBool()) {
+ out = value->asBool() ? "TRUE" : "FALSE";
+ return ReadFileResult::READ_OK;
+ }
+
+ return VariableStringHelper(out, value);
+}
+
+auto const VariableObjectHelper =
+ cmJSONObjectHelper<CacheVariable, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false)
+ .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false)
+ .Bind("value"_s, &CacheVariable::Value, VariableValueHelper);
+
+ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
+ const Json::Value* value)
+{
+ if (value->isBool()) {
+ out = CacheVariable{
+ /*Type=*/"BOOL",
+ /*Value=*/value->asBool() ? "TRUE" : "FALSE",
+ };
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isString()) {
+ out = CacheVariable{
+ /*Type=*/"",
+ /*Value=*/value->asString(),
+ };
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isObject()) {
+ out.emplace();
+ return VariableObjectHelper(*out, value);
+ }
+ if (value->isNull()) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+ return ReadFileResult::INVALID_VARIABLE;
+}
+
+auto const VariablesHelper =
+ cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
+
+auto const PresetStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
+ const Json::Value* value)
+{
+ if (!value || value->isNull()) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isString()) {
+ out = value->asString();
+ return ReadFileResult::READ_OK;
+ }
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const EnvironmentMapHelper =
+ cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ EnvironmentHelper);
+
+auto const PresetVectorStringHelper =
+ cmJSONVectorHelper<std::string, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ PresetStringHelper);
+
+ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out,
+ const Json::Value* value)
+{
+ out.clear();
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.push_back(value->asString());
+ return ReadFileResult::READ_OK;
+ }
+
+ return PresetVectorStringHelper(out, value);
+}
+
+auto const PresetBoolHelper = cmJSONBoolHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+auto const PresetOptionalBoolHelper =
+ cmJSONOptionalHelper<bool, ReadFileResult>(ReadFileResult::READ_OK,
+ PresetBoolHelper);
+
+auto const PresetIntHelper = cmJSONIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+auto const PresetOptionalIntHelper = cmJSONOptionalHelper<int, ReadFileResult>(
+ ReadFileResult::READ_OK, PresetIntHelper);
+
+auto const PresetVectorIntHelper = cmJSONVectorHelper<int, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper);
+
+auto const PresetWarningsHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false)
+ .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated,
+ PresetOptionalBoolHelper, false)
+ .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized,
+ PresetOptionalBoolHelper, false)
+ .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli,
+ PresetOptionalBoolHelper, false)
+ .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars,
+ PresetOptionalBoolHelper, false);
+
+auto const PresetErrorsHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false)
+ .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated,
+ PresetOptionalBoolHelper, false);
+
+auto const PresetDebugHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper,
+ false)
+ .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile,
+ PresetOptionalBoolHelper, false)
+ .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper,
+ false);
+
+ReadFileResult ArchToolsetStrategyHelper(
+ cm::optional<ArchToolsetStrategy>& out, const Json::Value* value)
+{
+ if (!value) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "set") {
+ out = ArchToolsetStrategy::Set;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "external") {
+ out = ArchToolsetStrategy::External;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)>
+ArchToolsetHelper(
+ std::string ConfigurePreset::*valueField,
+ cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField)
+{
+ auto const objectHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("value", valueField, PresetStringHelper, false)
+ .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false);
+ return [valueField, strategyField, objectHelper](
+ ConfigurePreset& out, const Json::Value* value) -> ReadFileResult {
+ if (!value) {
+ (out.*valueField).clear();
+ out.*strategyField = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.*valueField = value->asString();
+ out.*strategyField = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isObject()) {
+ return objectHelper(out, value);
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+ };
+}
+
+auto const ArchitectureHelper = ArchToolsetHelper(
+ &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy);
+auto const ToolsetHelper = ArchToolsetHelper(
+ &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy);
+
+auto const ConfigurePresetHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper)
+ .Bind("inherits"_s, &ConfigurePreset::Inherits,
+ PresetVectorOneOrMoreStringHelper, false)
+ .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_PRESET), false)
+ .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper,
+ false)
+ .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper,
+ false)
+ .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper,
+ false)
+ .Bind("architecture"_s, ArchitectureHelper, false)
+ .Bind("toolset"_s, ToolsetHelper, false)
+ .Bind("toolchainFile"_s, &ConfigurePreset::ToolchainFile,
+ PresetStringHelper, false)
+ .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper,
+ false)
+ .Bind("installDir"_s, &ConfigurePreset::InstallDir, PresetStringHelper,
+ false)
+ .Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false)
+ .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables,
+ VariablesHelper, false)
+ .Bind("environment"_s, &ConfigurePreset::Environment, EnvironmentMapHelper,
+ false)
+ .Bind("warnings"_s, PresetWarningsHelper, false)
+ .Bind("errors"_s, PresetErrorsHelper, false)
+ .Bind("debug"_s, PresetDebugHelper, false)
+ .Bind("condition"_s, &ConfigurePreset::ConditionEvaluator,
+ PresetConditionHelper, false);
+
+auto const BuildPresetHelper =
+ cmJSONObjectHelper<BuildPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &BuildPreset::Name, PresetStringHelper)
+ .Bind("inherits"_s, &BuildPreset::Inherits,
+ PresetVectorOneOrMoreStringHelper, false)
+ .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_PRESET), false)
+ .Bind("displayName"_s, &BuildPreset::DisplayName, PresetStringHelper,
+ false)
+ .Bind("description"_s, &BuildPreset::Description, PresetStringHelper,
+ false)
+ .Bind("environment"_s, &BuildPreset::Environment, EnvironmentMapHelper,
+ false)
+ .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset,
+ PresetStringHelper, false)
+ .Bind("inheritConfigureEnvironment"_s,
+ &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
+ false)
+ .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false)
+ .Bind("targets"_s, &BuildPreset::Targets,
+ PresetVectorOneOrMoreStringHelper, false)
+ .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper,
+ false)
+ .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper,
+ false)
+ .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false)
+ .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions,
+ PresetVectorStringHelper, false)
+ .Bind("condition"_s, &BuildPreset::ConditionEvaluator,
+ PresetConditionHelper, false);
+
+ReadFileResult TestPresetOutputVerbosityHelper(
+ TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value)
+{
+ if (!value) {
+ out = TestPreset::OutputOptions::VerbosityEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "default") {
+ out = TestPreset::OutputOptions::VerbosityEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "verbose") {
+ out = TestPreset::OutputOptions::VerbosityEnum::Verbose;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "extra") {
+ out = TestPreset::OutputOptions::VerbosityEnum::Extra;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalOutputVerbosityHelper =
+ cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ TestPresetOutputVerbosityHelper);
+
+auto const TestPresetOptionalOutputHelper =
+ cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress,
+ PresetOptionalBoolHelper, false)
+ .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity,
+ TestPresetOptionalOutputVerbosityHelper, false)
+ .Bind("debug"_s, &TestPreset::OutputOptions::Debug,
+ PresetOptionalBoolHelper, false)
+ .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure,
+ PresetOptionalBoolHelper, false)
+ .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet,
+ PresetOptionalBoolHelper, false)
+ .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile,
+ PresetStringHelper, false)
+ .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary,
+ PresetOptionalBoolHelper, false)
+ .Bind("subprojectSummary"_s,
+ &TestPreset::OutputOptions::SubprojectSummary,
+ PresetOptionalBoolHelper, false)
+ .Bind("maxPassedTestOutputSize"_s,
+ &TestPreset::OutputOptions::MaxPassedTestOutputSize,
+ PresetOptionalIntHelper, false)
+ .Bind("maxFailedTestOutputSize"_s,
+ &TestPreset::OutputOptions::MaxFailedTestOutputSize,
+ PresetOptionalIntHelper, false)
+ .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth,
+ PresetOptionalIntHelper, false));
+
+auto const TestPresetOptionalFilterIncludeIndexObjectHelper =
+ cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions,
+ ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_PRESET)
+ .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start,
+ PresetOptionalIntHelper, false)
+ .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End,
+ PresetOptionalIntHelper, false)
+ .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride,
+ PresetOptionalIntHelper, false)
+ .Bind("specificTests"_s,
+ &TestPreset::IncludeOptions::IndexOptions::SpecificTests,
+ PresetVectorIntHelper, false));
+
+ReadFileResult TestPresetOptionalFilterIncludeIndexHelper(
+ cm::optional<TestPreset::IncludeOptions::IndexOptions>& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.emplace();
+ out->IndexFile = value->asString();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isObject()) {
+ return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value);
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalFilterIncludeHelper =
+ cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("name"_s, &TestPreset::IncludeOptions::Name, PresetStringHelper,
+ false)
+ .Bind("label"_s, &TestPreset::IncludeOptions::Label, PresetStringHelper,
+ false)
+ .Bind("index"_s, &TestPreset::IncludeOptions::Index,
+ TestPresetOptionalFilterIncludeIndexHelper, false)
+ .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion,
+ PresetOptionalBoolHelper, false));
+
+auto const TestPresetOptionalFilterExcludeFixturesHelper =
+ cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions,
+ ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_PRESET)
+ .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any,
+ PresetStringHelper, false)
+ .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup,
+ PresetStringHelper, false)
+ .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup,
+ PresetStringHelper, false));
+
+auto const TestPresetOptionalFilterExcludeHelper =
+ cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("name"_s, &TestPreset::ExcludeOptions::Name, PresetStringHelper,
+ false)
+ .Bind("label"_s, &TestPreset::ExcludeOptions::Label, PresetStringHelper,
+ false)
+ .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures,
+ TestPresetOptionalFilterExcludeFixturesHelper, false));
+
+ReadFileResult TestPresetExecutionShowOnlyHelper(
+ TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value)
+{
+ if (!value || !value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "human") {
+ out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "json-v1") {
+ out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalExecutionShowOnlyHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ TestPresetExecutionShowOnlyHelper);
+
+ReadFileResult TestPresetExecutionModeHelper(
+ TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "until-fail") {
+ out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "until-pass") {
+ out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "after-timeout") {
+ out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalExecutionRepeatHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions,
+ ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_PRESET)
+ .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode,
+ TestPresetExecutionModeHelper, true)
+ .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count,
+ PresetIntHelper, true));
+
+ReadFileResult TestPresetExecutionNoTestsActionHelper(
+ TestPreset::ExecutionOptions::NoTestsActionEnum& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "default") {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "error") {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "ignore") {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalExecutionNoTestsActionHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ TestPresetExecutionNoTestsActionHelper);
+
+auto const TestPresetExecutionHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure,
+ PresetOptionalBoolHelper, false)
+ .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover,
+ PresetOptionalBoolHelper, false)
+ .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs,
+ PresetOptionalIntHelper, false)
+ .Bind("resourceSpecFile"_s,
+ &TestPreset::ExecutionOptions::ResourceSpecFile,
+ PresetStringHelper, false)
+ .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad,
+ PresetOptionalIntHelper, false)
+ .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly,
+ TestPresetOptionalExecutionShowOnlyHelper, false)
+ .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat,
+ TestPresetOptionalExecutionRepeatHelper, false)
+ .Bind("interactiveDebugging"_s,
+ &TestPreset::ExecutionOptions::InteractiveDebugging,
+ PresetOptionalBoolHelper, false)
+ .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom,
+ PresetOptionalBoolHelper, false)
+ .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout,
+ PresetOptionalIntHelper, false)
+ .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction,
+ TestPresetOptionalExecutionNoTestsActionHelper, false));
+
+auto const TestPresetFilterHelper =
+ cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("include"_s, &TestPreset::FilterOptions::Include,
+ TestPresetOptionalFilterIncludeHelper, false)
+ .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude,
+ TestPresetOptionalFilterExcludeHelper, false));
+
+auto const TestPresetHelper =
+ cmJSONObjectHelper<TestPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &TestPreset::Name, PresetStringHelper)
+ .Bind("inherits"_s, &TestPreset::Inherits,
+ PresetVectorOneOrMoreStringHelper, false)
+ .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_PRESET), false)
+ .Bind("displayName"_s, &TestPreset::DisplayName, PresetStringHelper, false)
+ .Bind("description"_s, &TestPreset::Description, PresetStringHelper, false)
+ .Bind("environment"_s, &TestPreset::Environment, EnvironmentMapHelper,
+ false)
+ .Bind("configurePreset"_s, &TestPreset::ConfigurePreset,
+ PresetStringHelper, false)
+ .Bind("inheritConfigureEnvironment"_s,
+ &TestPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
+ false)
+ .Bind("configuration"_s, &TestPreset::Configuration, PresetStringHelper,
+ false)
+ .Bind("overwriteConfigurationFile"_s,
+ &TestPreset::OverwriteConfigurationFile, PresetVectorStringHelper,
+ false)
+ .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper,
+ false)
+ .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false)
+ .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper,
+ false)
+ .Bind("condition"_s, &TestPreset::ConditionEvaluator,
+ PresetConditionHelper, false);
+
+auto const ConfigurePresetsHelper =
+ cmJSONVectorHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ ConfigurePresetHelper);
+
+auto const BuildPresetsHelper =
+ cmJSONVectorHelper<BuildPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ BuildPresetHelper);
+
+auto const TestPresetsHelper = cmJSONVectorHelper<TestPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper);
+
+auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
+
+auto const CMakeVersionHelper =
+ cmJSONObjectHelper<CMakeVersion, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
+ .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
+ .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
+ .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);
+
+auto const RootPresetsHelper =
+ cmJSONObjectHelper<RootPresets, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
+ .Bind<int>("version"_s, nullptr, VersionHelper)
+ .Bind("configurePresets"_s, &RootPresets::ConfigurePresets,
+ ConfigurePresetsHelper, false)
+ .Bind("buildPresets"_s, &RootPresets::BuildPresets, BuildPresetsHelper,
+ false)
+ .Bind("testPresets"_s, &RootPresets::TestPresets, TestPresetsHelper, false)
+ .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
+ CMakeVersionHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_ROOT), false);
+}
+
+cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
+ const std::string& filename, bool user)
+{
+ cmsys::ifstream fin(filename.c_str());
+ if (!fin) {
+ return ReadFileResult::FILE_NOT_FOUND;
+ }
+ // If there's a BOM, toss it.
+ cmsys::FStream::ReadBOM(fin);
+
+ Json::Value root;
+ Json::CharReaderBuilder builder;
+ Json::CharReaderBuilder::strictMode(&builder.settings_);
+ if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
+ return ReadFileResult::JSON_PARSE_ERROR;
+ }
+
+ int v = 0;
+ auto result = RootVersionHelper(v, &root);
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+ if (v < MIN_VERSION || v > MAX_VERSION) {
+ return ReadFileResult::UNRECOGNIZED_VERSION;
+ }
+ if (user) {
+ this->UserVersion = v;
+ } else {
+ this->Version = v;
+ }
+
+ // Support for build and test presets added in version 2.
+ if (v < 2 &&
+ (root.isMember("buildPresets") || root.isMember("testPresets"))) {
+ return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
+ }
+
+ RootPresets presets;
+ if ((result = RootPresetsHelper(presets, &root)) !=
+ ReadFileResult::READ_OK) {
+ return result;
+ }
+
+ unsigned int currentMajor = cmVersion::GetMajorVersion();
+ unsigned int currentMinor = cmVersion::GetMinorVersion();
+ unsigned int currentPatch = cmVersion::GetPatchVersion();
+ auto const& required = presets.CMakeMinimumRequired;
+ if (required.Major > currentMajor ||
+ (required.Major == currentMajor &&
+ (required.Minor > currentMinor ||
+ (required.Minor == currentMinor &&
+ (required.Patch > currentPatch))))) {
+ return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
+ }
+
+ for (auto& preset : presets.ConfigurePresets) {
+ preset.User = user;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<ConfigurePreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->ConfigurePresets
+ .emplace(std::make_pair(preset.Name, presetPair))
+ .second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for installDir presets added in version 3.
+ if (v < 3 && !preset.InstallDir.empty()) {
+ return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED;
+ }
+
+ // Support for conditions added in version 3.
+ if (v < 3 && preset.ConditionEvaluator) {
+ return ReadFileResult::CONDITION_UNSUPPORTED;
+ }
+
+ // Support for toolchainFile presets added in version 3.
+ if (v < 3 && !preset.ToolchainFile.empty()) {
+ return ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED;
+ }
+
+ this->ConfigurePresetOrder.push_back(preset.Name);
+ }
+
+ for (auto& preset : presets.BuildPresets) {
+ preset.User = user;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<BuildPreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for conditions added in version 3.
+ if (v < 3 && preset.ConditionEvaluator) {
+ return ReadFileResult::CONDITION_UNSUPPORTED;
+ }
+
+ this->BuildPresetOrder.push_back(preset.Name);
+ }
+
+ for (auto& preset : presets.TestPresets) {
+ preset.User = user;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<TestPreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for conditions added in version 3.
+ if (v < 3 && preset.ConditionEvaluator) {
+ return ReadFileResult::CONDITION_UNSUPPORTED;
+ }
+
+ this->TestPresetOrder.push_back(preset.Name);
+ }
+
+ return ReadFileResult::READ_OK;
+}
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index 438a0779a..ace73825a 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -734,7 +734,7 @@ void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir,
}
sf->SourceName = name;
std::string fname = sf->SourceName;
- if (ext && strlen(ext)) {
+ if (cmNonempty(ext)) {
fname += ".";
fname += ext;
}
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 620ba1979..7c469c84a 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -4,7 +4,6 @@
#include <algorithm>
#include <cctype>
-#include <cerrno>
#include <chrono>
#include <cstdio>
#include <cstdlib>
@@ -1613,8 +1612,33 @@ int cmCTest::GenerateDoneFile()
return 0;
}
+bool cmCTest::TryToChangeDirectory(std::string const& dir)
+{
+ cmCTestLog(this, OUTPUT,
+ "Internal ctest changing into directory: " << dir << std::endl);
+ cmsys::Status status = cmSystemTools::ChangeDirectory(dir);
+ if (!status) {
+ auto msg = "Failed to change working directory to \"" + dir +
+ "\" : " + status.GetString() + "\n";
+ cmCTestLog(this, ERROR_MESSAGE, msg);
+ return false;
+ }
+ return true;
+}
+
std::string cmCTest::Base64GzipEncodeFile(std::string const& file)
{
+ const std::string currDir = cmSystemTools::GetCurrentWorkingDirectory();
+ std::string parentDir = cmSystemTools::GetParentDirectory(file);
+
+ // Temporarily change to the file's directory so the tar gets created
+ // with a flat directory structure.
+ if (currDir != parentDir) {
+ if (!this->TryToChangeDirectory(parentDir)) {
+ return "";
+ }
+ }
+
std::string tarFile = file + "_temp.tar.gz";
std::vector<std::string> files;
files.push_back(file);
@@ -1629,6 +1653,12 @@ std::string cmCTest::Base64GzipEncodeFile(std::string const& file)
}
std::string base64 = this->Base64EncodeFile(tarFile);
cmSystemTools::RemoveFile(tarFile);
+
+ // Change back to the directory we started in.
+ if (currDir != parentDir) {
+ cmSystemTools::ChangeDirectory(currDir);
+ }
+
return base64;
}
@@ -2070,6 +2100,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
}
i++;
this->Impl->TestDir = std::string(args[i]);
+ } else if (this->CheckArgument(arg, "--output-junit"_s)) {
+ if (i >= args.size() - 1) {
+ errormsg = "'--output-junit' requires an argument";
+ 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;
}
cm::string_view noTestsPrefix = "--no-tests=";
@@ -2108,17 +2149,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
} else if (this->CheckArgument(arg, "-L"_s, "--label-regex") &&
i < args.size() - 1) {
i++;
- this->GetTestHandler()->SetPersistentOption("LabelRegularExpression",
- args[i].c_str());
- this->GetMemCheckHandler()->SetPersistentOption("LabelRegularExpression",
- args[i].c_str());
+ this->GetTestHandler()->AddPersistentMultiOption("LabelRegularExpression",
+ args[i]);
+ this->GetMemCheckHandler()->AddPersistentMultiOption(
+ "LabelRegularExpression", args[i]);
} else if (this->CheckArgument(arg, "-LE"_s, "--label-exclude") &&
i < args.size() - 1) {
i++;
- this->GetTestHandler()->SetPersistentOption(
- "ExcludeLabelRegularExpression", args[i].c_str());
- this->GetMemCheckHandler()->SetPersistentOption(
- "ExcludeLabelRegularExpression", args[i].c_str());
+ this->GetTestHandler()->AddPersistentMultiOption(
+ "ExcludeLabelRegularExpression", args[i]);
+ this->GetMemCheckHandler()->AddPersistentMultiOption(
+ "ExcludeLabelRegularExpression", args[i]);
}
else if (this->CheckArgument(arg, "-E"_s, "--exclude-regex") &&
@@ -2205,6 +2246,10 @@ bool cmCTest::ColoredOutputSupportedByConsole()
!clicolor_force.empty() && clicolor_force != "0") {
return true;
}
+ std::string clicolor;
+ if (cmSystemTools::GetEnv("CLICOLOR", clicolor) && clicolor == "0") {
+ return false;
+ }
return ConsoleIsNotDumb();
#endif
}
@@ -2221,7 +2266,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
cmCTestScriptHandler* ch = this->GetScriptHandler();
// -SR is an internal argument, -SP should be ignored when it is passed
if (!SRArgumentSpecified) {
- ch->AddConfigurationScript(args[i].c_str(), false);
+ ch->AddConfigurationScript(args[i], false);
}
}
@@ -2231,7 +2276,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
this->Impl->RunConfigurationScript = true;
i++;
cmCTestScriptHandler* ch = this->GetScriptHandler();
- ch->AddConfigurationScript(args[i].c_str(), true);
+ ch->AddConfigurationScript(args[i], true);
}
if (this->CheckArgument(arg, "-S"_s, "--script") && i < args.size() - 1) {
@@ -2240,7 +2285,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
cmCTestScriptHandler* ch = this->GetScriptHandler();
// -SR is an internal argument, -S should be ignored when it is passed
if (!SRArgumentSpecified) {
- ch->AddConfigurationScript(args[i].c_str(), true);
+ ch->AddConfigurationScript(args[i], true);
}
}
}
@@ -2268,6 +2313,15 @@ void cmCTest::SetPersistentOptionIfNotEmpty(const std::string& value,
}
}
+void cmCTest::AddPersistentMultiOptionIfNotEmpty(const std::string& value,
+ const std::string& optionName)
+{
+ if (!value.empty()) {
+ this->GetTestHandler()->AddPersistentMultiOption(optionName, value);
+ this->GetMemCheckHandler()->AddPersistentMultiOption(optionName, value);
+ }
+}
+
bool cmCTest::SetArgsFromPreset(const std::string& presetName,
bool listPresets)
{
@@ -2310,6 +2364,13 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
return false;
}
+ if (!expandedPreset->ConditionResult) {
+ cmSystemTools::Error(cmStrCat("Cannot use disabled test preset in ",
+ workingDirectory, ": \"", presetName, '"'));
+ settingsFile.PrintTestPresetList();
+ return false;
+ }
+
auto configurePresetPair =
settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset);
if (configurePresetPair == settingsFile.ConfigurePresets.end()) {
@@ -2412,7 +2473,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (expandedPreset->Filter->Include) {
this->SetPersistentOptionIfNotEmpty(
expandedPreset->Filter->Include->Name, "IncludeRegularExpression");
- this->SetPersistentOptionIfNotEmpty(
+ this->AddPersistentMultiOptionIfNotEmpty(
expandedPreset->Filter->Include->Label, "LabelRegularExpression");
if (expandedPreset->Filter->Include->Index) {
@@ -2445,7 +2506,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (expandedPreset->Filter->Exclude) {
this->SetPersistentOptionIfNotEmpty(
expandedPreset->Filter->Exclude->Name, "ExcludeRegularExpression");
- this->SetPersistentOptionIfNotEmpty(
+ this->AddPersistentMultiOptionIfNotEmpty(
expandedPreset->Filter->Exclude->Label,
"ExcludeLabelRegularExpression");
@@ -2823,13 +2884,7 @@ int cmCTest::ExecuteTests()
}
if (currDir != workDir) {
- cmCTestLog(this, OUTPUT,
- "Internal ctest changing into directory: " << workDir
- << std::endl);
- if (cmSystemTools::ChangeDirectory(workDir) != 0) {
- auto msg = "Failed to change working directory to \"" + workDir +
- "\" : " + std::strerror(errno) + "\n";
- cmCTestLog(this, ERROR_MESSAGE, msg);
+ if (!this->TryToChangeDirectory(workDir)) {
return 1;
}
}
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 4669a1cc2..551c116ad 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -463,6 +463,8 @@ public:
private:
void SetPersistentOptionIfNotEmpty(const std::string& value,
const std::string& optionName);
+ void AddPersistentMultiOptionIfNotEmpty(const std::string& value,
+ const std::string& optionName);
int GenerateNotesFile(const std::string& files);
@@ -534,6 +536,9 @@ private:
int RunCMakeAndTest(std::string* output);
int ExecuteTests();
+ /** return true iff change directory was successful */
+ bool TryToChangeDirectory(std::string const& dir);
+
struct Private;
std::unique_ptr<Private> Impl;
};
diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h
index ddfff32f6..72ab0450f 100644
--- a/Source/cmCommandLineArgument.h
+++ b/Source/cmCommandLineArgument.h
@@ -17,10 +17,25 @@ struct cmCommandLineArgument
OneOrMore
};
+ enum class RequiresSeparator
+ {
+ Yes,
+ No
+ };
+
+ enum class ParseMode
+ {
+ Valid,
+ Invalid,
+ SyntaxError,
+ ValueError
+ };
+
std::string InvalidSyntaxMessage;
std::string InvalidValueMessage;
std::string Name;
Values Type;
+ RequiresSeparator SeparatorNeeded;
std::function<FunctionSignature> StoreCall;
template <typename FunctionType>
@@ -29,6 +44,19 @@ struct cmCommandLineArgument
, InvalidValueMessage(cmStrCat("Invalid value used with ", n))
, Name(std::move(n))
, Type(t)
+ , SeparatorNeeded(RequiresSeparator::Yes)
+ , StoreCall(std::forward<FunctionType>(func))
+ {
+ }
+
+ template <typename FunctionType>
+ cmCommandLineArgument(std::string n, Values t, RequiresSeparator s,
+ FunctionType&& func)
+ : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
+ , InvalidValueMessage(cmStrCat("Invalid value used with ", n))
+ , Name(std::move(n))
+ , Type(t)
+ , SeparatorNeeded(s)
, StoreCall(std::forward<FunctionType>(func))
{
}
@@ -40,14 +68,39 @@ struct cmCommandLineArgument
, InvalidValueMessage(std::move(failedMsg))
, Name(std::move(n))
, Type(t)
+ , SeparatorNeeded(RequiresSeparator::Yes)
+ , StoreCall(std::forward<FunctionType>(func))
+ {
+ }
+
+ template <typename FunctionType>
+ cmCommandLineArgument(std::string n, std::string failedMsg, Values t,
+ RequiresSeparator s, FunctionType&& func)
+ : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
+ , InvalidValueMessage(std::move(failedMsg))
+ , Name(std::move(n))
+ , Type(t)
+ , SeparatorNeeded(s)
, StoreCall(std::forward<FunctionType>(func))
{
}
bool matches(std::string const& input) const
{
- return (this->Type == Values::Zero) ? (input == this->Name)
- : cmHasPrefix(input, this->Name);
+ bool matched = false;
+ if (this->Type == Values::Zero) {
+ matched = (input == this->Name);
+ } else if (this->SeparatorNeeded == RequiresSeparator::No) {
+ matched = cmHasPrefix(input, this->Name);
+ } else if (cmHasPrefix(input, this->Name)) {
+ if (input.size() == this->Name.size()) {
+ matched = true;
+ } else {
+ matched =
+ (input[this->Name.size()] == '=' || input[this->Name.size()] == ' ');
+ }
+ }
+ return matched;
}
template <typename T, typename... CallState>
@@ -55,13 +108,6 @@ struct cmCommandLineArgument
std::vector<std::string> const& allArgs,
CallState&&... state) const
{
- enum class ParseMode
- {
- Valid,
- Invalid,
- SyntaxError,
- ValueError
- };
ParseMode parseState = ParseMode::Valid;
if (this->Type == Values::Zero) {
@@ -95,19 +141,10 @@ struct cmCommandLineArgument
index = nextValueIndex;
}
} else {
- // parse the string to get the value
- auto possible_value = cm::string_view(input).substr(this->Name.size());
- if (possible_value.empty()) {
- parseState = ParseMode::ValueError;
- } else if (possible_value[0] == '=') {
- possible_value.remove_prefix(1);
- if (possible_value.empty()) {
- parseState = ParseMode::ValueError;
- }
- }
+ auto value = this->extract_single_value(input, parseState);
if (parseState == ParseMode::Valid) {
- parseState = this->StoreCall(std::string(possible_value),
- std::forward<CallState>(state)...)
+ parseState =
+ this->StoreCall(value, std::forward<CallState>(state)...)
? ParseMode::Valid
: ParseMode::Invalid;
}
@@ -145,7 +182,13 @@ struct cmCommandLineArgument
index = (nextValueIndex - 1);
}
} else {
- parseState = ParseMode::SyntaxError;
+ auto value = this->extract_single_value(input, parseState);
+ if (parseState == ParseMode::Valid) {
+ parseState =
+ this->StoreCall(value, std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ }
}
}
@@ -157,4 +200,24 @@ struct cmCommandLineArgument
}
return (parseState == ParseMode::Valid);
}
+
+private:
+ std::string extract_single_value(std::string const& input,
+ ParseMode& parseState) const
+ {
+ // parse the string to get the value
+ auto possible_value = cm::string_view(input).substr(this->Name.size());
+ if (possible_value.empty()) {
+ parseState = ParseMode::ValueError;
+ } else if (possible_value[0] == '=') {
+ possible_value.remove_prefix(1);
+ if (possible_value.empty()) {
+ parseState = ParseMode::ValueError;
+ }
+ }
+ if (parseState == ParseMode::Valid && possible_value[0] == ' ') {
+ possible_value.remove_prefix(1);
+ }
+ return std::string(possible_value);
+ }
};
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 228cff7ae..7c2e20c01 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -15,6 +15,7 @@
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmProperty.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -241,8 +242,7 @@ std::string cmCommonTargetGenerator::GetManifests(const std::string& config)
manifests.reserve(manifest_srcs.size());
for (cmSourceFile const* manifest_src : manifest_srcs) {
manifests.push_back(this->LocalCommonGenerator->ConvertToOutputFormat(
- this->LocalCommonGenerator->MaybeConvertToRelativePath(
- this->LocalCommonGenerator->GetWorkingDirectory(),
+ this->LocalCommonGenerator->MaybeRelativeToWorkDir(
manifest_src->GetFullPath()),
cmOutputConverter::SHELL));
}
@@ -292,3 +292,24 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
this->LocalCommonGenerator->AppendFlags(flags, vflag.str());
}
}
+
+std::string cmCommonTargetGenerator::GetLinkerLauncher(
+ const std::string& config)
+{
+ std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
+ cmProp launcherProp =
+ this->GeneratorTarget->GetProperty(lang + "_LINKER_LAUNCHER");
+ if (cmNonempty(launcherProp)) {
+ // Convert ;-delimited list to single string
+ std::vector<std::string> args = cmExpandedList(*launcherProp, true);
+ if (!args.empty()) {
+ args[0] = this->LocalCommonGenerator->ConvertToOutputFormat(
+ args[0], cmOutputConverter::SHELL);
+ for (std::string& i : cmMakeRange(args.begin() + 1, args.end())) {
+ i = this->LocalCommonGenerator->EscapeForShell(i);
+ }
+ return cmJoin(args, " ");
+ }
+ }
+ return std::string();
+}
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
index fba6b0a5f..a156a41af 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -64,6 +64,8 @@ protected:
const std::string& config) const;
std::string ComputeTargetCompilePDB(const std::string& config) const;
+ std::string GetLinkerLauncher(const std::string& config);
+
private:
using ByLanguageMap = std::map<std::string, std::string>;
struct ByConfig
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 5341e8d8c..0b27e34c2 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -7,6 +7,7 @@
#include <cstdio>
#include <iterator>
#include <sstream>
+#include <unordered_map>
#include <utility>
#include <cm/memory>
@@ -263,6 +264,12 @@ cmComputeLinkDepends::Compute()
this->FinalLinkEntries.push_back(e);
}
}
+ // Place explicitly linked object files in the front. The linker will
+ // always use them anyway, and they may depend on symbols from libraries.
+ // Append in reverse order since we reverse the final order below.
+ for (int i : cmReverseRange(this->ObjectEntries)) {
+ this->FinalLinkEntries.emplace_back(this->EntryList[i]);
+ }
// Reverse the resulting order since we iterated in reverse.
std::reverse(this->FinalLinkEntries.begin(), this->FinalLinkEntries.end());
@@ -328,6 +335,27 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
return index;
}
+void cmComputeLinkDepends::AddLinkObject(cmLinkItem const& item)
+{
+ // Check if the item entry has already been added.
+ auto lei = this->LinkEntryIndex.find(item);
+ if (lei != this->LinkEntryIndex.end()) {
+ return;
+ }
+
+ // Allocate a spot for the item entry.
+ lei = this->AllocateLinkEntry(item);
+
+ // Initialize the item entry.
+ int index = lei->second;
+ LinkEntry& entry = this->EntryList[index];
+ entry.Item = BT<std::string>(item.AsStr(), item.Backtrace);
+ entry.IsObject = true;
+
+ // Record explicitly linked object files separately.
+ this->ObjectEntries.emplace_back(index);
+}
+
void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe)
{
// Get this entry representation.
@@ -343,6 +371,13 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe)
entry.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY;
// This target provides its own link interface information.
this->AddLinkEntries(depender_index, iface->Libraries);
+ this->AddLinkObjects(iface->Objects);
+ for (auto const& language : iface->Languages) {
+ auto runtimeEntries = iface->LanguageRuntimeLibraries.find(language);
+ if (runtimeEntries != iface->LanguageRuntimeLibraries.end()) {
+ this->AddLinkEntries(depender_index, runtimeEntries->second);
+ }
+ }
if (isIface) {
return;
@@ -487,6 +522,14 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
cmLinkImplementation const* impl =
this->Target->GetLinkImplementation(this->Config);
this->AddLinkEntries(-1, impl->Libraries);
+ this->AddLinkObjects(impl->Objects);
+
+ for (auto const& language : impl->Languages) {
+ auto runtimeEntries = impl->LanguageRuntimeLibraries.find(language);
+ if (runtimeEntries != impl->LanguageRuntimeLibraries.end()) {
+ this->AddLinkEntries(-1, runtimeEntries->second);
+ }
+ }
for (cmLinkItem const& wi : impl->WrongConfigLibraries) {
this->CheckWrongConfigItem(wi);
}
@@ -546,6 +589,13 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
}
}
+void cmComputeLinkDepends::AddLinkObjects(std::vector<cmLinkItem> const& objs)
+{
+ for (cmLinkItem const& obj : objs) {
+ this->AddLinkObject(obj);
+ }
+}
+
cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index,
const std::string& name)
{
diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h
index 902500aaf..72316f1aa 100644
--- a/Source/cmComputeLinkDepends.h
+++ b/Source/cmComputeLinkDepends.h
@@ -42,6 +42,7 @@ public:
cmGeneratorTarget const* Target = nullptr;
bool IsSharedDep = false;
bool IsFlag = false;
+ bool IsObject = false;
};
using EntryVector = std::vector<LinkEntry>;
@@ -65,10 +66,12 @@ private:
std::map<cmLinkItem, int>::iterator AllocateLinkEntry(
cmLinkItem const& item);
int AddLinkEntry(cmLinkItem const& item);
+ void AddLinkObject(cmLinkItem const& item);
void AddVarLinkEntries(int depender_index, const char* value);
void AddDirectLinkEntries();
template <typename T>
void AddLinkEntries(int depender_index, std::vector<T> const& libs);
+ void AddLinkObjects(std::vector<cmLinkItem> const& objs);
cmLinkItem ResolveLinkItem(int depender_index, const std::string& name);
// One entry for each unique item.
@@ -153,6 +156,9 @@ private:
std::set<cmGeneratorTarget const*> OldWrongConfigItems;
void CheckWrongConfigItem(cmLinkItem const& item);
+ // Record of explicitly linked object files.
+ std::vector<int> ObjectEntries;
+
int ComponentOrderId;
cmTargetLinkLibraryType LinkType;
bool HasConfig;
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 6225a4a9e..d15da0c96 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -309,6 +309,13 @@ cmComputeLinkInformation::cmComputeLinkInformation(
this->LibLinkSuffix =
this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
}
+ if (cmProp flag = this->Makefile->GetDefinition(
+ "CMAKE_" + this->LinkLanguage + "_LINK_OBJECT_FILE_FLAG")) {
+ this->ObjLinkFileFlag = *flag;
+ } else {
+ this->ObjLinkFileFlag =
+ this->Makefile->GetSafeDefinition("CMAKE_LINK_OBJECT_FILE_FLAG");
+ }
// Get options needed to specify RPATHs.
this->RuntimeUseChrpath = false;
@@ -514,7 +521,8 @@ bool cmComputeLinkInformation::Compute()
if (linkEntry.IsSharedDep) {
this->AddSharedDepItem(linkEntry.Item, linkEntry.Target);
} else {
- this->AddItem(linkEntry.Item, linkEntry.Target);
+ this->AddItem(linkEntry.Item, linkEntry.Target,
+ linkEntry.IsObject ? ItemIsObject::Yes : ItemIsObject::No);
}
}
@@ -577,10 +585,10 @@ void cmComputeLinkInformation::AddImplicitLinkInfo()
this->Target->GetLinkClosure(this->Config);
for (std::string const& li : lc->Languages) {
- if (li == "CUDA") {
+ if (li == "CUDA" || li == "HIP") {
// These need to go before the other implicit link information
// as they could require symbols from those other library
- // Currently restricted to CUDA as it is the only language
+ // Currently restricted as CUDA and HIP are the only languages
// we have documented runtime behavior controls for
this->AddRuntimeLinkLibrary(li);
}
@@ -634,7 +642,8 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
}
void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
- cmGeneratorTarget const* tgt)
+ cmGeneratorTarget const* tgt,
+ ItemIsObject isObject)
{
// Compute the proper name to use to link this library.
const std::string& config = this->Config;
@@ -659,14 +668,15 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
std::string exe = tgt->GetFullPath(config, artifact, true);
linkItem += exe;
- this->Items.emplace_back(BT<std::string>(linkItem, item.Backtrace), true,
- tgt);
+ this->Items.emplace_back(BT<std::string>(linkItem, item.Backtrace),
+ ItemIsPath::Yes, ItemIsObject::No, tgt);
this->Depends.push_back(std::move(exe));
} else if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
// Add the interface library as an item so it can be considered as part
// of COMPATIBLE_INTERFACE_ enforcement. The generators will ignore
// this for the actual link line.
- this->Items.emplace_back(std::string(), false, tgt);
+ this->Items.emplace_back(std::string(), ItemIsPath::No, ItemIsObject::No,
+ tgt);
// Also add the item the interface specifies to be used in its place.
std::string const& libName = tgt->GetImportedLibName(config);
@@ -701,6 +711,10 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
this->AddTargetItem(lib, tgt);
this->AddLibraryRuntimeInfo(lib.Value, tgt);
+ if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY &&
+ this->Target->IsDLLPlatform()) {
+ this->AddRuntimeDLL(tgt);
+ }
}
} else {
// This is not a CMake target. Use the name given.
@@ -715,7 +729,7 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
} else {
// Use the full path given to the library file.
this->Depends.push_back(item.Value);
- this->AddFullItem(item);
+ this->AddFullItem(item, isObject);
this->AddLibraryRuntimeInfo(item.Value);
}
} else {
@@ -728,6 +742,13 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
void cmComputeLinkInformation::AddSharedDepItem(BT<std::string> const& item,
const cmGeneratorTarget* tgt)
{
+ // Record dependencies on DLLs.
+ if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY &&
+ this->Target->IsDLLPlatform() &&
+ this->SharedDependencyMode != SharedDepModeLink) {
+ this->AddRuntimeDLL(tgt);
+ }
+
// If dropping shared library dependencies, ignore them.
if (this->SharedDependencyMode == SharedDepModeNone) {
return;
@@ -799,6 +820,14 @@ void cmComputeLinkInformation::AddSharedDepItem(BT<std::string> const& item,
}
}
+void cmComputeLinkInformation::AddRuntimeDLL(cmGeneratorTarget const* tgt)
+{
+ if (std::find(this->RuntimeDLLs.begin(), this->RuntimeDLLs.end(), tgt) ==
+ this->RuntimeDLLs.end()) {
+ this->RuntimeDLLs.emplace_back(tgt);
+ }
+}
+
void cmComputeLinkInformation::ComputeLinkTypeInfo()
{
// Check whether archives may actually be shared libraries.
@@ -1019,10 +1048,10 @@ void cmComputeLinkInformation::SetCurrentLinkType(LinkType lt)
if (this->LinkTypeEnabled) {
switch (this->CurrentLinkType) {
case LinkStatic:
- this->Items.emplace_back(this->StaticLinkTypeFlag, false);
+ this->Items.emplace_back(this->StaticLinkTypeFlag, ItemIsPath::No);
break;
case LinkShared:
- this->Items.emplace_back(this->SharedLinkTypeFlag, false);
+ this->Items.emplace_back(this->SharedLinkTypeFlag, ItemIsPath::No);
break;
default:
break;
@@ -1065,10 +1094,11 @@ void cmComputeLinkInformation::AddTargetItem(BT<std::string> const& item,
}
// Now add the full path to the library.
- this->Items.emplace_back(item, true, target);
+ this->Items.emplace_back(item, ItemIsPath::Yes, ItemIsObject::No, target);
}
-void cmComputeLinkInformation::AddFullItem(BT<std::string> const& item)
+void cmComputeLinkInformation::AddFullItem(BT<std::string> const& item,
+ ItemIsObject isObject)
{
// Check for the implicit link directory special case.
if (this->CheckImplicitDirItem(item.Value)) {
@@ -1119,7 +1149,7 @@ void cmComputeLinkInformation::AddFullItem(BT<std::string> const& item)
}
// Now add the full path to the library.
- this->Items.emplace_back(item, true);
+ this->Items.emplace_back(item, ItemIsPath::Yes, isObject);
}
bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
@@ -1207,7 +1237,7 @@ void cmComputeLinkInformation::AddUserItem(BT<std::string> const& item,
this->SetCurrentLinkType(this->StartLinkType);
// Use the item verbatim.
- this->Items.emplace_back(item, false);
+ this->Items.emplace_back(item, ItemIsPath::No);
return;
}
@@ -1277,7 +1307,8 @@ void cmComputeLinkInformation::AddUserItem(BT<std::string> const& item,
// Create an option to ask the linker to search for the library.
std::string out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix);
- this->Items.emplace_back(BT<std::string>(out, item.Backtrace), false);
+ this->Items.emplace_back(BT<std::string>(out, item.Backtrace),
+ ItemIsPath::No);
// Here we could try to find the library the linker will find and
// add a runtime information entry for it. It would probably not be
@@ -1309,13 +1340,13 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
if (this->GlobalGenerator->IsXcode()) {
// Add framework path - it will be handled by Xcode after it's added to
// "Link Binary With Libraries" build phase
- this->Items.emplace_back(item, true);
+ this->Items.emplace_back(item, ItemIsPath::Yes);
} else {
// Add the item using the -framework option.
- this->Items.emplace_back(std::string("-framework"), false);
+ this->Items.emplace_back(std::string("-framework"), ItemIsPath::No);
cmOutputConverter converter(this->Makefile->GetStateSnapshot());
fw = converter.EscapeForShell(fw);
- this->Items.emplace_back(fw, false);
+ this->Items.emplace_back(fw, ItemIsPath::No);
}
}
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 9fec70206..7fe30b3bb 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -35,17 +35,33 @@ public:
~cmComputeLinkInformation();
bool Compute();
+ enum class ItemIsPath
+ {
+ No,
+ Yes,
+ };
+
+ enum class ItemIsObject
+ {
+ No,
+ Yes,
+ };
+
struct Item
{
Item() = default;
- Item(BT<std::string> v, bool p, cmGeneratorTarget const* target = nullptr)
+ Item(BT<std::string> v, ItemIsPath isPath,
+ ItemIsObject isObject = ItemIsObject::No,
+ cmGeneratorTarget const* target = nullptr)
: Value(std::move(v))
- , IsPath(p)
+ , IsPath(isPath)
+ , IsObject(isObject)
, Target(target)
{
}
BT<std::string> Value;
- bool IsPath = true;
+ ItemIsPath IsPath = ItemIsPath::Yes;
+ ItemIsObject IsObject = ItemIsObject::No;
cmGeneratorTarget const* Target = nullptr;
};
using ItemVector = std::vector<Item>;
@@ -64,12 +80,21 @@ public:
std::string GetRPathString(bool for_install) const;
std::string GetChrpathString() const;
std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked() const;
+ std::vector<cmGeneratorTarget const*> const& GetRuntimeDLLs() const
+ {
+ return this->RuntimeDLLs;
+ }
std::string const& GetLibLinkFileFlag() const
{
return this->LibLinkFileFlag;
}
+ std::string const& GetObjLinkFileFlag() const
+ {
+ return this->ObjLinkFileFlag;
+ }
+
std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; }
std::string GetRPathLinkString() const;
@@ -78,9 +103,11 @@ public:
const cmGeneratorTarget* GetTarget() { return this->Target; }
private:
- void AddItem(BT<std::string> const& item, const cmGeneratorTarget* tgt);
+ void AddItem(BT<std::string> const& item, const cmGeneratorTarget* tgt,
+ ItemIsObject isObject = ItemIsObject::No);
void AddSharedDepItem(BT<std::string> const& item,
cmGeneratorTarget const* tgt);
+ void AddRuntimeDLL(cmGeneratorTarget const* tgt);
// Output information.
ItemVector Items;
@@ -89,6 +116,7 @@ private:
std::vector<std::string> FrameworkPaths;
std::vector<std::string> RuntimeSearchPath;
std::set<cmGeneratorTarget const*> SharedLibrariesLinked;
+ std::vector<cmGeneratorTarget const*> RuntimeDLLs;
// Context information.
cmGeneratorTarget const* const Target;
@@ -112,6 +140,7 @@ private:
const char* LoaderFlag;
std::string LibLinkFlag;
std::string LibLinkFileFlag;
+ std::string ObjLinkFileFlag;
std::string LibLinkSuffix;
std::string RuntimeFlag;
std::string RuntimeSep;
@@ -153,7 +182,7 @@ private:
// Handling of link items.
void AddTargetItem(BT<std::string> const& item,
const cmGeneratorTarget* target);
- void AddFullItem(BT<std::string> const& item);
+ void AddFullItem(BT<std::string> const& item, ItemIsObject isObject);
bool CheckImplicitDirItem(std::string const& item);
void AddUserItem(BT<std::string> const& item, bool pathNotKnown);
void AddFrameworkItem(std::string const& item);
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 85a9d9cf1..76712f4eb 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -20,6 +20,7 @@
#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -227,32 +228,19 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
this->AddInterfaceDepends(depender_index, lib, it, emitted);
}
}
+ for (cmLinkItem const& obj : impl->Objects) {
+ if (cmSourceFile const* o = depender->Makefile->GetSource(
+ obj.AsStr(), cmSourceFileLocationKind::Known)) {
+ this->AddObjectDepends(depender_index, o, emitted);
+ }
+ }
}
// Add dependencies on object libraries not otherwise handled above.
std::vector<cmSourceFile const*> objectFiles;
depender->GetExternalObjects(objectFiles, it);
for (cmSourceFile const* o : objectFiles) {
- std::string const& objLib = o->GetObjectLibrary();
- if (!objLib.empty()) {
- cmLinkItem const& objItem =
- depender->ResolveLinkItem(objLib, cmListFileBacktrace());
- if (emitted.insert(objItem).second) {
- if (depender->GetType() != cmStateEnums::EXECUTABLE &&
- depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
- depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
- depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
- depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
- this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR,
- "Only executables and libraries may reference target objects.",
- depender->GetBacktrace());
- return;
- }
- const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(
- objLib, false);
- }
- }
+ this->AddObjectDepends(depender_index, o, emitted);
}
}
}
@@ -293,6 +281,12 @@ void cmComputeTargetDepends::AddInterfaceDepends(
this->AddInterfaceDepends(depender_index, libBT, config, emitted);
}
}
+ for (cmLinkItem const& obj : iface->Objects) {
+ if (cmSourceFile const* o = depender->Makefile->GetSource(
+ obj.AsStr(), cmSourceFileLocationKind::Known)) {
+ this->AddObjectDepends(depender_index, o, emitted);
+ }
+ }
}
}
@@ -319,6 +313,34 @@ void cmComputeTargetDepends::AddInterfaceDepends(
}
}
+void cmComputeTargetDepends::AddObjectDepends(int depender_index,
+ cmSourceFile const* o,
+ std::set<cmLinkItem>& emitted)
+{
+ std::string const& objLib = o->GetObjectLibrary();
+ if (objLib.empty()) {
+ return;
+ }
+ cmGeneratorTarget const* depender = this->Targets[depender_index];
+ cmLinkItem const& objItem =
+ depender->ResolveLinkItem(objLib, cmListFileBacktrace());
+ if (emitted.insert(objItem).second) {
+ if (depender->GetType() != cmStateEnums::EXECUTABLE &&
+ depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "Only executables and libraries may reference target objects.",
+ depender->GetBacktrace());
+ return;
+ }
+ const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib,
+ false);
+ }
+}
+
void cmComputeTargetDepends::AddTargetDepend(int depender_index,
cmLinkItem const& dependee_name,
bool linking, bool cross)
diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h
index 3517844d6..0eab3683d 100644
--- a/Source/cmComputeTargetDepends.h
+++ b/Source/cmComputeTargetDepends.h
@@ -16,6 +16,7 @@ class cmComputeComponentGraph;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmLinkItem;
+class cmSourceFile;
class cmTargetDependSet;
/** \class cmComputeTargetDepends
@@ -71,6 +72,8 @@ private:
cmListFileBacktrace const& dependee_backtrace,
const std::string& config,
std::set<cmLinkItem>& emitted);
+ void AddObjectDepends(int depender_index, cmSourceFile const* o,
+ std::set<cmLinkItem>& emitted);
cmGlobalGenerator* GlobalGenerator;
bool DebugMode;
bool NoCycles;
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 62bc52691..f99592cc0 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -654,10 +654,10 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
this->IsKeyword(keyIS_NEWER_THAN, *argP1)) {
int fileIsNewer = 0;
- bool success = cmSystemTools::FileTimeCompare(
+ cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare(
arg->GetValue(), (argP2)->GetValue(), &fileIsNewer);
this->HandleBinaryOp(
- (!success || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg,
+ (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg,
newArgs, argP1, argP2);
}
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 6672aa676..8ecf2648f 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -8,6 +8,7 @@
#include <sstream>
#include <utility>
+#include <cm/string_view>
#include <cmext/string_view>
#include "cmsys/Directory.hxx"
@@ -188,6 +189,8 @@ SETUP_LANGUAGE(cuda_properties, CUDA);
// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
SETUP_LANGUAGE(fortran_properties, Fortran);
// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
+SETUP_LANGUAGE(hip_properties, HIP);
+// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
SETUP_LANGUAGE(objc_properties, OBJC);
// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
SETUP_LANGUAGE(objcxx_properties, OBJCXX);
@@ -200,6 +203,8 @@ SETUP_LANGUAGE(swift_properties, Swift);
std::string const kCMAKE_CUDA_ARCHITECTURES = "CMAKE_CUDA_ARCHITECTURES";
std::string const kCMAKE_CUDA_RUNTIME_LIBRARY = "CMAKE_CUDA_RUNTIME_LIBRARY";
std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS";
+std::string const kCMAKE_HIP_ARCHITECTURES = "CMAKE_HIP_ARCHITECTURES";
+std::string const kCMAKE_HIP_RUNTIME_LIBRARY = "CMAKE_HIP_RUNTIME_LIBRARY";
std::string const kCMAKE_ISPC_INSTRUCTION_SETS = "CMAKE_ISPC_INSTRUCTION_SETS";
std::string const kCMAKE_ISPC_HEADER_SUFFIX = "CMAKE_ISPC_HEADER_SUFFIX";
std::string const kCMAKE_LINK_SEARCH_END_STATIC =
@@ -217,6 +222,7 @@ std::string const kCMAKE_POSITION_INDEPENDENT_CODE =
std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT";
std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE";
std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK";
+std::string const kCMAKE_ARMClang_CMP0123 = "CMAKE_ARMClang_CMP0123";
std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES =
"CMAKE_TRY_COMPILE_OSX_ARCHITECTURES";
std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES =
@@ -272,6 +278,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
LanguageStandardState cState("C");
LanguageStandardState cudaState("CUDA");
LanguageStandardState cxxState("CXX");
+ LanguageStandardState hipState("HIP");
LanguageStandardState objcState("OBJC");
LanguageStandardState objcxxState("OBJCXX");
std::vector<std::string> targets;
@@ -321,6 +328,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} 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;
@@ -426,6 +434,9 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
if (!cudaState.Validate(this->Makefile)) {
return -1;
}
+ if (!hipState.Validate(this->Makefile)) {
+ return -1;
+ }
if (!cxxState.Validate(this->Makefile)) {
return -1;
}
@@ -552,6 +563,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
fprintf(fout, "cmake_policy(SET CMP0104 OLD)\n");
}
+ /* Set ARMClang cpu/arch policy to match outer project. */
+ if (cmProp cmp0123 =
+ this->Makefile->GetDefinition(kCMAKE_ARMClang_CMP0123)) {
+ fprintf(fout, "cmake_policy(SET CMP0123 %s)\n",
+ *cmp0123 == "NEW"_s ? "NEW" : "OLD");
+ }
+
std::string projectLangs;
for (std::string const& li : testLangs) {
projectLangs += " " + li;
@@ -706,6 +724,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
vars.insert(
&fortran_properties[lang_property_start],
&fortran_properties[lang_property_start + lang_property_size]);
+ vars.insert(&hip_properties[lang_property_start],
+ &hip_properties[lang_property_start + lang_property_size]);
vars.insert(&objc_properties[lang_property_start],
&objc_properties[lang_property_start + lang_property_size]);
vars.insert(
@@ -718,6 +738,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
vars.insert(kCMAKE_CUDA_ARCHITECTURES);
vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY);
vars.insert(kCMAKE_ENABLE_EXPORTS);
+ vars.insert(kCMAKE_HIP_ARCHITECTURES);
+ vars.insert(kCMAKE_HIP_RUNTIME_LIBRARY);
vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS);
vars.insert(kCMAKE_ISPC_HEADER_SUFFIX);
vars.insert(kCMAKE_LINK_SEARCH_END_STATIC);
@@ -752,6 +774,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
vars.insert(
&fortran_properties[pie_property_start],
&fortran_properties[pie_property_start + pie_property_size]);
+ vars.insert(&hip_properties[pie_property_start],
+ &hip_properties[pie_property_start + pie_property_size]);
vars.insert(&objc_properties[pie_property_start],
&objc_properties[pie_property_start + pie_property_size]);
vars.insert(
@@ -826,6 +850,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
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());
@@ -833,7 +858,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
bool honorStandard = true;
if (cState.DidNone() && cxxState.DidNone() && objcState.DidNone() &&
- objcxxState.DidNone() && cudaState.DidNone()) {
+ objcxxState.DidNone() && cudaState.DidNone() && hipState.DidNone()) {
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
case cmPolicies::WARN:
warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
@@ -863,6 +888,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
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,
@@ -885,6 +912,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
cState.WriteProperties(fout, targetName);
cxxState.WriteProperties(fout, targetName);
cudaState.WriteProperties(fout, targetName);
+ hipState.WriteProperties(fout, targetName);
objcState.WriteProperties(fout, targetName);
objcxxState.WriteProperties(fout, targetName);
@@ -1015,17 +1043,21 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir)
// cannot delete them immediately. Try a few times.
cmSystemTools::WindowsFileRetry retry =
cmSystemTools::GetWindowsFileRetry();
- while (!cmSystemTools::RemoveFile(fullPath) && --retry.Count &&
- cmSystemTools::FileExists(fullPath)) {
+ cmsys::Status status;
+ while (!((status = cmSystemTools::RemoveFile(fullPath))) &&
+ --retry.Count && cmSystemTools::FileExists(fullPath)) {
cmSystemTools::Delay(retry.Delay);
}
if (retry.Count == 0)
#else
- if (!cmSystemTools::RemoveFile(fullPath))
+ cmsys::Status status = cmSystemTools::RemoveFile(fullPath);
+ if (!status)
#endif
{
- std::string m = "Remove failed on file: " + fullPath;
- cmSystemTools::ReportLastSystemError(m.c_str());
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The file:\n ", fullPath,
+ "\ncould not be removed:\n ", status.GetString()));
}
}
}
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx
index 3001ae09a..a2fac738c 100644
--- a/Source/cmCreateTestSourceList.cxx
+++ b/Source/cmCreateTestSourceList.cxx
@@ -90,10 +90,15 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args,
std::replace(func_name.begin(), func_name.end(), ' ', '_');
std::replace(func_name.begin(), func_name.end(), '/', '_');
std::replace(func_name.begin(), func_name.end(), ':', '_');
+ bool already_declared =
+ std::find(tests_func_name.begin(), tests_func_name.end(), func_name) !=
+ tests_func_name.end();
tests_func_name.push_back(func_name);
- forwardDeclareCode += "int ";
- forwardDeclareCode += func_name;
- forwardDeclareCode += "(int, char*[]);\n";
+ if (!already_declared) {
+ forwardDeclareCode += "int ";
+ forwardDeclareCode += func_name;
+ forwardDeclareCode += "(int, char*[]);\n";
+ }
}
std::string functionMapCode;
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index f6b998984..ec60ff755 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -150,3 +150,13 @@ void cmCustomCommand::SetCMP0116Status(cmPolicies::PolicyStatus cmp0116)
{
this->CMP0116Status = cmp0116;
}
+
+const std::string& cmCustomCommand::GetTarget() const
+{
+ return this->Target;
+}
+
+void cmCustomCommand::SetTarget(const std::string& target)
+{
+ this->Target = target;
+}
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index e22c7a406..5cbd3d17a 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -100,6 +100,10 @@ public:
cmPolicies::PolicyStatus GetCMP0116Status() const;
void SetCMP0116Status(cmPolicies::PolicyStatus cmp0116);
+ /** Set/Get the associated target */
+ const std::string& GetTarget() const;
+ void SetTarget(const std::string& target);
+
private:
std::vector<std::string> Outputs;
std::vector<std::string> Byproducts;
@@ -107,6 +111,7 @@ private:
cmCustomCommandLines CommandLines;
cmListFileBacktrace Backtrace;
cmImplicitDependsList ImplicitDepends;
+ std::string Target;
std::string Comment;
std::string WorkingDirectory;
std::string Depfile;
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 4329cafc4..5a2683bb8 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -29,7 +29,7 @@ namespace {
std::string EvaluateSplitConfigGenex(
cm::string_view input, cmGeneratorExpression const& ge, cmLocalGenerator* lg,
bool useOutputConfig, std::string const& outputConfig,
- std::string const& commandConfig,
+ std::string const& commandConfig, cmGeneratorTarget const* target,
std::set<BT<std::pair<std::string, bool>>>* utils = nullptr)
{
std::string result;
@@ -87,7 +87,7 @@ std::string EvaluateSplitConfigGenex(
// Evaluate this genex in the selected configuration.
std::unique_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(std::string(genex));
- result += cge->Evaluate(lg, *config);
+ result += cge->Evaluate(lg, *config, target);
// Record targets referenced by the genex.
if (utils) {
@@ -114,7 +114,8 @@ std::vector<std::string> EvaluateDepends(std::vector<std::string> const& paths,
std::string const& ep =
EvaluateSplitConfigGenex(p, ge, lg, /*useOutputConfig=*/true,
/*outputConfig=*/outputConfig,
- /*commandConfig=*/commandConfig);
+ /*commandConfig=*/commandConfig,
+ /*target=*/nullptr);
cm::append(depends, cmExpandedList(ep));
}
for (std::string& p : depends) {
@@ -139,20 +140,41 @@ std::vector<std::string> EvaluateOutputs(std::vector<std::string> const& paths,
}
return outputs;
}
+
+std::string EvaluateDepfile(std::string const& path,
+ cmGeneratorExpression const& ge,
+ cmLocalGenerator* lg, std::string const& config)
+{
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(path);
+ return cge->Evaluate(lg, config);
+}
}
cmCustomCommandGenerator::cmCustomCommandGenerator(
cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg,
- bool transformDepfile, cm::optional<std::string> crossConfig)
+ bool transformDepfile, cm::optional<std::string> crossConfig,
+ std::function<std::string(const std::string&, const std::string&)>
+ computeInternalDepfile)
: CC(&cc)
, OutputConfig(crossConfig ? *crossConfig : config)
, CommandConfig(std::move(config))
+ , Target(cc.GetTarget())
, LG(lg)
, OldStyle(cc.GetEscapeOldStyle())
, MakeVars(cc.GetEscapeAllowMakeVars())
, EmulatorsWithArguments(cc.GetCommandLines().size())
+ , ComputeInternalDepfile(std::move(computeInternalDepfile))
{
+ if (!this->ComputeInternalDepfile) {
+ this->ComputeInternalDepfile =
+ [this](const std::string& cfg, const std::string& file) -> std::string {
+ return this->GetInternalDepfileName(cfg, file);
+ };
+ }
+
cmGeneratorExpression ge(cc.GetBacktrace());
+ cmGeneratorTarget const* target{ lg->FindGeneratorTargetToUse(
+ this->Target) };
const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines();
for (cmCustomCommandLine const& cmdline : cmdlines) {
@@ -162,7 +184,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
for (std::string const& clarg : cmdline) {
std::string parsed_arg = EvaluateSplitConfigGenex(
clarg, ge, this->LG, useOutputConfig, this->OutputConfig,
- this->CommandConfig, &this->Utilities);
+ this->CommandConfig, target, &this->Utilities);
if (this->CC->GetCommandExpandLists()) {
cm::append(argv, cmExpandedList(parsed_arg));
} else {
@@ -205,8 +227,11 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
case cmDepfileFormat::GccDepfile:
argv.emplace_back("gccdepfile");
break;
- case cmDepfileFormat::VsTlog:
- argv.emplace_back("vstlog");
+ case cmDepfileFormat::MakeDepfile:
+ argv.emplace_back("makedepfile");
+ break;
+ case cmDepfileFormat::MSBuildAdditionalInputs:
+ argv.emplace_back("MSBuildAdditionalInputs");
break;
}
argv.push_back(this->LG->GetSourceDirectory());
@@ -228,9 +253,9 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
const std::string& workingdirectory = this->CC->GetWorkingDirectory();
if (!workingdirectory.empty()) {
- this->WorkingDirectory =
- EvaluateSplitConfigGenex(workingdirectory, ge, this->LG, true,
- this->OutputConfig, this->CommandConfig);
+ this->WorkingDirectory = EvaluateSplitConfigGenex(
+ workingdirectory, ge, this->LG, true, this->OutputConfig,
+ this->CommandConfig, target);
// Convert working directory to a full path.
if (!this->WorkingDirectory.empty()) {
std::string const& build_dir = this->LG->GetCurrentBinaryDirectory();
@@ -381,9 +406,20 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c,
}
}
+std::string cmCustomCommandGenerator::GetDepfile() const
+{
+ const auto& depfile = this->CC->GetDepfile();
+ if (depfile.empty()) {
+ return "";
+ }
+
+ cmGeneratorExpression ge(this->CC->GetBacktrace());
+ return EvaluateDepfile(depfile, ge, this->LG, this->OutputConfig);
+}
+
std::string cmCustomCommandGenerator::GetFullDepfile() const
{
- std::string depfile = this->CC->GetDepfile();
+ std::string depfile = this->GetDepfile();
if (depfile.empty()) {
return "";
}
@@ -394,27 +430,34 @@ std::string cmCustomCommandGenerator::GetFullDepfile() const
return cmSystemTools::CollapseFullPath(depfile);
}
-std::string cmCustomCommandGenerator::GetInternalDepfile() const
+std::string cmCustomCommandGenerator::GetInternalDepfileName(
+ const std::string& /*config*/, const std::string& depfile)
{
- std::string depfile = this->GetFullDepfile();
- if (depfile.empty()) {
- return "";
- }
-
cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
std::string extension;
switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) {
case cmDepfileFormat::GccDepfile:
+ case cmDepfileFormat::MakeDepfile:
extension = ".d";
break;
- case cmDepfileFormat::VsTlog:
- extension = ".tlog";
+ case cmDepfileFormat::MSBuildAdditionalInputs:
+ extension = ".AdditionalInputs";
break;
}
return cmStrCat(this->LG->GetBinaryDirectory(), "/CMakeFiles/d/",
hash.HashString(depfile), extension);
}
+std::string cmCustomCommandGenerator::GetInternalDepfile() const
+{
+ std::string depfile = this->GetFullDepfile();
+ if (depfile.empty()) {
+ return "";
+ }
+
+ return this->ComputeInternalDepfile(this->OutputConfig, depfile);
+}
+
const char* cmCustomCommandGenerator::GetComment() const
{
return this->CC->GetComment();
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 4be5b3fd2..73a8d387d 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <functional>
#include <set>
#include <string>
#include <utility>
@@ -19,9 +20,12 @@ class cmLocalGenerator;
class cmCustomCommandGenerator
{
+ std::string GetInternalDepfileName(const std::string&, const std::string&);
+
cmCustomCommand const* CC;
std::string OutputConfig;
std::string CommandConfig;
+ std::string Target;
cmLocalGenerator* LG;
bool OldStyle;
bool MakeVars;
@@ -32,15 +36,19 @@ class cmCustomCommandGenerator
std::vector<std::string> Depends;
std::string WorkingDirectory;
std::set<BT<std::pair<std::string, bool>>> Utilities;
+ std::function<std::string(const std::string&, const std::string&)>
+ ComputeInternalDepfile;
void FillEmulatorsWithArguments();
std::vector<std::string> GetCrossCompilingEmulator(unsigned int c) const;
const char* GetArgv0Location(unsigned int c) const;
public:
- cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config,
- cmLocalGenerator* lg, bool transformDepfile = true,
- cm::optional<std::string> crossConfig = {});
+ cmCustomCommandGenerator(
+ cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg,
+ bool transformDepfile = true, cm::optional<std::string> crossConfig = {},
+ std::function<std::string(const std::string&, const std::string&)>
+ computeInternalDepfile = {});
cmCustomCommandGenerator(const cmCustomCommandGenerator&) = delete;
cmCustomCommandGenerator(cmCustomCommandGenerator&&) = default;
cmCustomCommandGenerator& operator=(const cmCustomCommandGenerator&) =
@@ -57,6 +65,7 @@ public:
std::vector<std::string> const& GetDepends() const;
std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const;
bool HasOnlyEmptyCommandLines() const;
+ std::string GetDepfile() const;
std::string GetFullDepfile() const;
std::string GetInternalDepfile() const;
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index 566c3bf78..46c7e3e77 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -229,11 +229,10 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends,
void cmDepends::SetIncludePathFromLanguage(const std::string& lang)
{
// Look for the new per "TARGET_" variant first:
- cmProp includePath = nullptr;
std::string includePathVar =
cmStrCat("CMAKE_", lang, "_TARGET_INCLUDE_PATH");
cmMakefile* mf = this->LocalGenerator->GetMakefile();
- includePath = mf->GetDefinition(includePathVar);
+ cmProp includePath = mf->GetDefinition(includePathVar);
if (includePath) {
cmExpandList(*includePath, this->IncludePath);
} else {
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 60e8cbf2c..da37d4531 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -90,13 +90,10 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
std::set<std::string> dependencies;
bool haveDeps = false;
- std::string binDir = this->LocalGenerator->GetBinaryDirectory();
-
// Compute a path to the object file to write to the internal depend file.
// Any existing content of the internal depend file has already been
// loaded in ValidDeps with this path as a key.
- std::string obj_i =
- this->LocalGenerator->MaybeConvertToRelativePath(binDir, obj);
+ std::string obj_i = this->LocalGenerator->MaybeRelativeToTopBinDir(obj);
if (this->ValidDeps != nullptr) {
auto const tmpIt = this->ValidDeps->find(obj_i);
@@ -228,7 +225,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
}
for (std::string const& dep : dependencies) {
std::string dependee = this->LocalGenerator->ConvertToMakefilePath(
- this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
+ this->LocalGenerator->MaybeRelativeToTopBinDir(dep));
if (supportLongLineDepend) {
makeDepends << ' ' << lineContinue << ' ' << dependee;
} else {
diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx
index 09f55997b..bf599ffaf 100644
--- a/Source/cmDependsCompiler.cxx
+++ b/Source/cmDependsCompiler.cxx
@@ -192,21 +192,19 @@ void cmDependsCompiler::WriteDependencies(
bool supportLongLineDepend = static_cast<cmGlobalUnixMakefileGenerator3*>(
this->LocalGenerator->GetGlobalGenerator())
->SupportsLongLineDependencies();
- const auto& binDir = this->LocalGenerator->GetBinaryDirectory();
cmDepends::DependencyMap makeDependencies(dependencies);
std::unordered_set<cm::string_view> phonyTargets;
// external dependencies file
for (auto& node : makeDependencies) {
auto target = this->LocalGenerator->ConvertToMakefilePath(
- this->LocalGenerator->MaybeConvertToRelativePath(binDir, node.first));
+ this->LocalGenerator->MaybeRelativeToTopBinDir(node.first));
auto& deps = node.second;
- std::transform(
- deps.cbegin(), deps.cend(), deps.begin(),
- [this, &binDir](const std::string& dep) {
- return this->LocalGenerator->ConvertToMakefilePath(
- this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
- });
+ std::transform(deps.cbegin(), deps.cend(), deps.begin(),
+ [this](const std::string& dep) {
+ return this->LocalGenerator->ConvertToMakefilePath(
+ this->LocalGenerator->MaybeRelativeToTopBinDir(dep));
+ });
bool first_dep = true;
if (supportLongLineDepend) {
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 1a06f3170..bca26b9ca 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -17,8 +17,6 @@
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmProperty.h"
-#include "cmStateDirectory.h"
-#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -192,8 +190,6 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
cmGeneratedFileStream fcStream(fcName);
fcStream << "# Remove fortran modules provided by this target.\n";
fcStream << "FILE(REMOVE";
- std::string currentBinDir =
- this->LocalGenerator->GetCurrentBinaryDirectory();
for (std::string const& i : provides) {
std::string mod_upper = cmStrCat(mod_dir, '/');
std::string mod_lower = cmStrCat(mod_dir, '/');
@@ -201,13 +197,13 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
std::string stamp = cmStrCat(stamp_dir, '/', i, ".stamp");
fcStream << "\n"
" \""
- << this->MaybeConvertToRelativePath(currentBinDir, mod_lower)
+ << this->LocalGenerator->MaybeRelativeToCurBinDir(mod_lower)
<< "\"\n"
" \""
- << this->MaybeConvertToRelativePath(currentBinDir, mod_upper)
+ << this->LocalGenerator->MaybeRelativeToCurBinDir(mod_upper)
<< "\"\n"
" \""
- << this->MaybeConvertToRelativePath(currentBinDir, stamp)
+ << this->LocalGenerator->MaybeRelativeToCurBinDir(stamp)
<< "\"\n";
}
fcStream << " )\n";
@@ -317,8 +313,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
std::string const& src = info.Source;
// Write the include dependencies to the output stream.
- std::string binDir = this->LocalGenerator->GetBinaryDirectory();
- std::string obj_i = this->MaybeConvertToRelativePath(binDir, obj);
+ std::string obj_i = this->LocalGenerator->MaybeRelativeToTopBinDir(obj);
std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i);
internalDepends << obj_i << "\n " << src << '\n';
if (!info.Includes.empty()) {
@@ -333,7 +328,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
}
for (std::string const& i : info.Includes) {
std::string dependee = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, i));
+ this->LocalGenerator->MaybeRelativeToTopBinDir(i));
if (supportLongLineDepend) {
makeDepends << ' ' << lineContinue << ' ' << dependee;
} else {
@@ -360,7 +355,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
if (!required->second.empty()) {
// This module is known. Depend on its timestamp file.
std::string stampFile = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, required->second));
+ this->LocalGenerator->MaybeRelativeToTopBinDir(required->second));
makeDepends << obj_m << ": " << stampFile << '\n';
} else {
// This module is not known to CMake. Try to locate it where
@@ -368,7 +363,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
std::string module;
if (this->FindModule(i, module)) {
module = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, module));
+ this->LocalGenerator->MaybeRelativeToTopBinDir(module));
makeDepends << obj_m << ": " << module << '\n';
}
}
@@ -387,10 +382,10 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
// try various cases for the real mod file name.
std::string modFile = cmStrCat(mod_dir, '/', i);
modFile = this->LocalGenerator->ConvertToOutputFormat(
- this->MaybeConvertToRelativePath(binDir, modFile),
+ this->LocalGenerator->MaybeRelativeToTopBinDir(modFile),
cmOutputConverter::SHELL);
std::string stampFile = cmStrCat(stamp_dir, '/', i, ".stamp");
- stampFile = this->MaybeConvertToRelativePath(binDir, stampFile);
+ stampFile = this->LocalGenerator->MaybeRelativeToTopBinDir(stampFile);
std::string const stampFileForShell =
this->LocalGenerator->ConvertToOutputFormat(stampFile,
cmOutputConverter::SHELL);
@@ -425,7 +420,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
// the target finishes building.
std::string driver = cmStrCat(this->TargetDirectory, "/build");
driver = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, driver));
+ this->LocalGenerator->MaybeRelativeToTopBinDir(driver));
makeDepends << driver << ": " << obj_m << ".provides.build\n";
}
@@ -681,13 +676,3 @@ bool cmDependsFortran::ModulesDiffer(const std::string& modFile,
// content.
return cmFortranStreamsDiffer(finModFile, finStampFile);
}
-
-std::string cmDependsFortran::MaybeConvertToRelativePath(
- std::string const& base, std::string const& path)
-{
- if (!this->LocalGenerator->GetStateSnapshot().GetDirectory().ContainsBoth(
- base, path)) {
- return path;
- }
- return cmSystemTools::ForceToRelativePath(base, path);
-}
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index e377a2c33..0d407bc3b 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -85,8 +85,4 @@ protected:
// Internal implementation details.
std::unique_ptr<cmDependsFortranInternals> Internal;
-
-private:
- std::string MaybeConvertToRelativePath(std::string const& base,
- std::string const& path);
};
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index deffdb646..9a474e32c 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -168,6 +168,9 @@ public:
// Return the recorded ELF type.
cmELF::FileType GetFileType() const { return this->ELFType; }
+ // Return the recorded machine.
+ std::uint16_t GetMachine() const { return this->Machine; }
+
protected:
// Data common to all ELF class implementations.
@@ -183,6 +186,9 @@ protected:
// The ELF file type.
cmELF::FileType ELFType;
+ // The ELF architecture.
+ std::uint16_t Machine;
+
// Whether we need to byte-swap structures read from the stream.
bool NeedSwap;
@@ -478,6 +484,8 @@ cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external,
}
}
+ this->Machine = this->ELFHeader.e_machine;
+
// Load the section headers.
this->SectionHeaders.resize(this->ELFHeader.e_shnum);
for (ELF_Half i = 0; i < this->ELFHeader.e_shnum; ++i) {
@@ -757,6 +765,14 @@ cmELF::FileType cmELF::GetFileType() const
return FileTypeInvalid;
}
+std::uint16_t cmELF::GetMachine() const
+{
+ if (this->Valid()) {
+ return this->Internal->GetMachine();
+ }
+ return 0;
+}
+
unsigned int cmELF::GetNumberOfSections() const
{
if (this->Valid()) {
diff --git a/Source/cmELF.h b/Source/cmELF.h
index c479e2b95..f88ebe992 100644
--- a/Source/cmELF.h
+++ b/Source/cmELF.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstdint>
#include <iosfwd>
#include <memory>
#include <string>
@@ -72,6 +73,9 @@ public:
/** Get the type of the file opened. */
FileType GetFileType() const;
+ /** Get the machine of the file opened. */
+ std::uint16_t GetMachine() const;
+
/** Get the number of ELF sections present. */
unsigned int GetNumberOfSections() const;
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 7015a0129..dd611de6b 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -924,13 +924,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.18 (this upper limit may be reviewed
+ // policy settings for up to CMake 3.19 (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.6...3.18)\n";
+ << "cmake_policy(VERSION 2.6...3.19)\n";
/* clang-format on */
}
@@ -1229,7 +1229,7 @@ bool cmExportFileGenerator::PopulateExportProperties(
return false;
}
cmProp propertyValue = targetProperties.GetPropertyValue(prop);
- if (propertyValue == nullptr) {
+ if (!propertyValue) {
// Asked to export a property that isn't defined on the target. Do not
// consider this an error, there's just nothing to export.
continue;
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index f21720174..df1426104 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -366,10 +366,11 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
continue;
}
- // check whether it is a C/C++/CUDA implementation file
+ // check whether it is a C/C++/CUDA/HIP implementation file
bool isCFile = false;
std::string lang = s->GetOrDetermineLanguage();
- if (lang == "C" || lang == "CXX" || lang == "CUDA") {
+ if (lang == "C" || lang == "CXX" || lang == "CUDA" ||
+ lang == "HIP") {
std::string const& srcext = s->GetExtension();
isCFile = cm->IsACLikeSourceExtension(srcext);
}
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index ccfd72798..672089c73 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -248,17 +248,17 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
// now we have both, decide which one to use
std::string valueToUse;
- if (!envVarSet && cacheValue == nullptr) {
+ if (!envVarSet && !cacheValue) {
// nothing known, do nothing
valueToUse.clear();
- } else if (envVarSet && cacheValue == nullptr) {
+ } else if (envVarSet && !cacheValue) {
// The variable is in the env, but not in the cache. Use it and put it
// in the cache
valueToUse = envVarValue;
mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName.c_str(),
cmStateEnums::STRING, true);
mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory());
- } else if (!envVarSet && cacheValue != nullptr) {
+ } else if (!envVarSet && cacheValue) {
// It is already in the cache, but not in the env, so use it from the cache
valueToUse = *cacheValue;
} else {
@@ -655,7 +655,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
xml.EndElement(); // extension
} else {
std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
- if (systemName == "CYGWIN") {
+ if (systemName == "CYGWIN" || systemName == "MSYS") {
xml.StartElement("extension");
xml.Attribute("id", "org.eclipse.cdt.core.Cygwin_PE");
xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
@@ -916,8 +916,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
// and UTILITY targets
for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) {
const auto& targets = lgen->GetGeneratorTargets();
- std::string subdir = lgen->MaybeConvertToRelativePath(
- this->HomeOutputDirectory, lgen->GetCurrentBinaryDirectory());
+ std::string subdir =
+ lgen->MaybeRelativeToTopBinDir(lgen->GetCurrentBinaryDirectory());
if (subdir == ".") {
subdir.clear();
}
@@ -1097,7 +1097,7 @@ void cmExtraEclipseCDT4Generator::AppendStorageScanners(
compiler = "gcc";
}
- // the following right now hardcodes gcc behaviour :-/
+ // the following right now hardcodes gcc behavior :-/
std::string compilerArgs =
"-E -P -v -dD ${plugin_state_location}/${specs_file}";
if (!arg1.empty()) {
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
index 54c311452..9153119c4 100644
--- a/Source/cmExtraKateGenerator.cxx
+++ b/Source/cmExtraKateGenerator.cxx
@@ -130,7 +130,7 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator& lg,
if (targetName == "edit_cache") {
cmProp editCommand =
localGen->GetMakefile()->GetDefinition("CMAKE_EDIT_COMMAND");
- if (editCommand == nullptr ||
+ if (!editCommand ||
strstr(editCommand->c_str(), "ccmake") != nullptr) {
insertTarget = false;
}
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index a92f6e328..52965bb57 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -435,7 +435,8 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes(
lg->GetIncludeDirectories(includes, target, language, config);
std::string includesString =
- lg->GetIncludeFlags(includes, target, language, true, false, config);
+ lg->GetIncludeFlags(includes, target, language, config, false,
+ cmLocalGenerator::IncludePathStyle::Absolute);
return includesString;
}
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index d2a9becf4..d529f5268 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -686,7 +686,7 @@ std::string cmFileAPI::NoSupportedVersion(
// The "codemodel" object kind.
-static unsigned int const CodeModelV2Minor = 2;
+static unsigned int const CodeModelV2Minor = 3;
void cmFileAPI::BuildClientRequestCodeModel(
ClientRequest& r, std::vector<RequestVersion> const& versions)
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index c96eecda1..a2b5460c1 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -15,16 +15,26 @@
#include <utility>
#include <vector>
+#include <cm/string_view>
#include <cmext/algorithm>
#include <cm3p/json/value.h>
#include "cmCryptoHash.h"
+#include "cmExportSet.h"
#include "cmFileAPI.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmInstallDirectoryGenerator.h"
+#include "cmInstallExportGenerator.h"
+#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
+#include "cmInstallGetRuntimeDependenciesGenerator.h"
+#include "cmInstallImportedRuntimeArtifactsGenerator.h"
+#include "cmInstallRuntimeDependencySet.h"
+#include "cmInstallRuntimeDependencySetGenerator.h"
+#include "cmInstallScriptGenerator.h"
#include "cmInstallSubdirectoryGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
@@ -42,103 +52,17 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
+#include "cmTargetExport.h"
#include "cmake.h"
namespace {
-class Codemodel
-{
- cmFileAPI& FileAPI;
- unsigned long Version;
-
- Json::Value DumpPaths();
- Json::Value DumpConfigurations();
- Json::Value DumpConfiguration(std::string const& config);
-
-public:
- Codemodel(cmFileAPI& fileAPI, unsigned long version);
- Json::Value Dump();
-};
-
-class CodemodelConfig
-{
- cmFileAPI& FileAPI;
- unsigned long Version;
- std::string const& Config;
- std::string TopSource;
- std::string TopBuild;
-
- struct Directory
- {
- cmStateSnapshot Snapshot;
- cmLocalGenerator const* LocalGenerator = nullptr;
- Json::Value TargetIndexes = Json::arrayValue;
- Json::ArrayIndex ProjectIndex;
- bool HasInstallRule = false;
- };
- std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
- DirectoryMap;
- std::vector<Directory> Directories;
-
- struct Project
- {
- cmStateSnapshot Snapshot;
- static const Json::ArrayIndex NoParentIndex =
- static_cast<Json::ArrayIndex>(-1);
- Json::ArrayIndex ParentIndex = NoParentIndex;
- Json::Value ChildIndexes = Json::arrayValue;
- Json::Value DirectoryIndexes = Json::arrayValue;
- Json::Value TargetIndexes = Json::arrayValue;
- };
- std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
- ProjectMap;
- std::vector<Project> Projects;
-
- void ProcessDirectories();
-
- Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg);
- Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s);
-
- Json::ArrayIndex AddProject(cmStateSnapshot s);
-
- Json::Value DumpTargets();
- Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti);
-
- Json::Value DumpDirectories();
- Json::Value DumpDirectory(Directory& d);
-
- Json::Value DumpProjects();
- Json::Value DumpProject(Project& p);
-
- Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s);
-
-public:
- CodemodelConfig(cmFileAPI& fileAPI, unsigned long version,
- std::string const& config);
- Json::Value Dump();
-};
+using TargetIndexMapType =
+ std::unordered_map<cmGeneratorTarget const*, Json::ArrayIndex>;
std::string RelativeIfUnder(std::string const& top, std::string const& in)
{
- std::string out;
- if (in == top) {
- out = ".";
- } else if (cmSystemTools::IsSubDirectory(in, top)) {
- out = in.substr(top.size() + 1);
- } else {
- out = in;
- }
- return out;
-}
-
-std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild)
-{
- cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
- std::string path = RelativeIfUnder(
- topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
- std::string hash = hasher.HashString(path);
- hash.resize(20, '0');
- return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash;
+ return cmSystemTools::RelativeIfUnder(top, in);
}
class JBTIndex
@@ -290,6 +214,91 @@ Json::Value BacktraceData::Dump()
return backtraceGraph;
}
+class Codemodel
+{
+ cmFileAPI& FileAPI;
+ unsigned long Version;
+
+ Json::Value DumpPaths();
+ Json::Value DumpConfigurations();
+ Json::Value DumpConfiguration(std::string const& config);
+
+public:
+ Codemodel(cmFileAPI& fileAPI, unsigned long version);
+ Json::Value Dump();
+};
+
+class CodemodelConfig
+{
+ cmFileAPI& FileAPI;
+ unsigned long Version;
+ std::string const& Config;
+ std::string TopSource;
+ std::string TopBuild;
+
+ struct Directory
+ {
+ cmStateSnapshot Snapshot;
+ cmLocalGenerator const* LocalGenerator = nullptr;
+ Json::Value TargetIndexes = Json::arrayValue;
+ Json::ArrayIndex ProjectIndex;
+ bool HasInstallRule = false;
+ };
+ std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
+ DirectoryMap;
+ std::vector<Directory> Directories;
+
+ struct Project
+ {
+ cmStateSnapshot Snapshot;
+ static const Json::ArrayIndex NoParentIndex =
+ static_cast<Json::ArrayIndex>(-1);
+ Json::ArrayIndex ParentIndex = NoParentIndex;
+ Json::Value ChildIndexes = Json::arrayValue;
+ Json::Value DirectoryIndexes = Json::arrayValue;
+ Json::Value TargetIndexes = Json::arrayValue;
+ };
+ std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
+ ProjectMap;
+ std::vector<Project> Projects;
+
+ TargetIndexMapType TargetIndexMap;
+
+ void ProcessDirectories();
+
+ Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg);
+ Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s);
+
+ Json::ArrayIndex AddProject(cmStateSnapshot s);
+
+ Json::Value DumpTargets();
+ Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti);
+
+ Json::Value DumpDirectories();
+ Json::Value DumpDirectory(Directory& d);
+ Json::Value DumpDirectoryObject(Directory& d);
+
+ Json::Value DumpProjects();
+ Json::Value DumpProject(Project& p);
+
+ Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s);
+
+public:
+ CodemodelConfig(cmFileAPI& fileAPI, unsigned long version,
+ std::string const& config);
+ Json::Value Dump();
+};
+
+std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild)
+{
+ cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
+ std::string path = RelativeIfUnder(
+ topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
+ std::string hash = hasher.HashString(path);
+ hash.resize(20, '0');
+ return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash;
+}
+
struct CompileData
{
struct IncludeEntry
@@ -367,6 +376,31 @@ struct hash<CompileData>
} // namespace std
namespace {
+class DirectoryObject
+{
+ cmLocalGenerator const* LG = nullptr;
+ std::string const& Config;
+ TargetIndexMapType& TargetIndexMap;
+ std::string TopSource;
+ std::string TopBuild;
+ BacktraceData Backtraces;
+
+ void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt);
+
+ Json::Value DumpPaths();
+ Json::Value DumpInstallers();
+ Json::Value DumpInstaller(cmInstallGenerator* gen);
+ Json::Value DumpInstallerExportTargets(cmExportSet* exp);
+ Json::Value DumpInstallerPath(std::string const& top,
+ std::string const& fromPathIn,
+ std::string const& toPath);
+
+public:
+ DirectoryObject(cmLocalGenerator const* lg, std::string const& config,
+ TargetIndexMapType& targetIndexMap);
+ Json::Value Dump();
+};
+
class Target
{
cmGeneratorTarget* GT;
@@ -663,6 +697,8 @@ Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt,
target["projectIndex"] = pi;
this->Projects[pi].TargetIndexes.append(ti);
+ this->TargetIndexMap[gt] = ti;
+
return target;
}
@@ -677,7 +713,7 @@ Json::Value CodemodelConfig::DumpDirectories()
Json::Value CodemodelConfig::DumpDirectory(Directory& d)
{
- Json::Value directory = Json::objectValue;
+ Json::Value directory = this->DumpDirectoryObject(d);
std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource();
directory["source"] = RelativeIfUnder(this->TopSource, sourceDir);
@@ -717,6 +753,31 @@ Json::Value CodemodelConfig::DumpDirectory(Directory& d)
return directory;
}
+Json::Value CodemodelConfig::DumpDirectoryObject(Directory& d)
+{
+ std::string prefix = "directory";
+ std::string sourceDirRel = RelativeIfUnder(
+ this->TopSource, d.Snapshot.GetDirectory().GetCurrentSource());
+ std::string buildDirRel = RelativeIfUnder(
+ this->TopBuild, d.Snapshot.GetDirectory().GetCurrentBinary());
+ if (!cmSystemTools::FileIsFullPath(buildDirRel)) {
+ prefix = cmStrCat(prefix, '-', buildDirRel);
+ } else if (!cmSystemTools::FileIsFullPath(sourceDirRel)) {
+ prefix = cmStrCat(prefix, '-', sourceDirRel);
+ }
+ for (char& c : prefix) {
+ if (c == '/' || c == '\\') {
+ c = '.';
+ }
+ }
+ if (!this->Config.empty()) {
+ prefix += "-" + this->Config;
+ }
+
+ DirectoryObject dir(d.LocalGenerator, this->Config, this->TargetIndexMap);
+ return this->FileAPI.MaybeJsonFile(dir.Dump(), prefix);
+}
+
Json::Value CodemodelConfig::DumpProjects()
{
Json::Value projects = Json::arrayValue;
@@ -760,6 +821,281 @@ Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s)
return minimumCMakeVersion;
}
+DirectoryObject::DirectoryObject(cmLocalGenerator const* lg,
+ std::string const& config,
+ TargetIndexMapType& targetIndexMap)
+ : LG(lg)
+ , Config(config)
+ , TargetIndexMap(targetIndexMap)
+ , TopSource(lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory())
+ , TopBuild(
+ lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory())
+ , Backtraces(this->TopSource)
+{
+}
+
+Json::Value DirectoryObject::Dump()
+{
+ Json::Value directoryObject = Json::objectValue;
+ directoryObject["paths"] = this->DumpPaths();
+ directoryObject["installers"] = this->DumpInstallers();
+ directoryObject["backtraceGraph"] = this->Backtraces.Dump();
+ return directoryObject;
+}
+
+void DirectoryObject::AddBacktrace(Json::Value& object,
+ cmListFileBacktrace const& bt)
+{
+ if (JBTIndex backtrace = this->Backtraces.Add(bt)) {
+ object["backtrace"] = backtrace.Index;
+ }
+}
+
+Json::Value DirectoryObject::DumpPaths()
+{
+ Json::Value paths = Json::objectValue;
+
+ std::string const& sourceDir = this->LG->GetCurrentSourceDirectory();
+ paths["source"] = RelativeIfUnder(this->TopSource, sourceDir);
+
+ std::string const& buildDir = this->LG->GetCurrentBinaryDirectory();
+ paths["build"] = RelativeIfUnder(this->TopBuild, buildDir);
+
+ return paths;
+}
+
+Json::Value DirectoryObject::DumpInstallers()
+{
+ Json::Value installers = Json::arrayValue;
+ for (const auto& gen : this->LG->GetMakefile()->GetInstallGenerators()) {
+ Json::Value installer = this->DumpInstaller(gen.get());
+ if (!installer.empty()) {
+ installers.append(std::move(installer)); // NOLINT(*)
+ }
+ }
+ return installers;
+}
+
+Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
+{
+ assert(gen);
+ Json::Value installer = Json::objectValue;
+
+ // Exclude subdirectory installers and file(GET_RUNTIME_DEPENDENCIES)
+ // installers. They are implementation details.
+ if (dynamic_cast<cmInstallSubdirectoryGenerator*>(gen) ||
+ dynamic_cast<cmInstallGetRuntimeDependenciesGenerator*>(gen)) {
+ return installer;
+ }
+
+ // Exclude installers not used in this configuration.
+ if (!gen->InstallsForConfig(this->Config)) {
+ return installer;
+ }
+
+ // Add fields specific to each kind of install generator.
+ if (auto* installTarget = dynamic_cast<cmInstallTargetGenerator*>(gen)) {
+ cmInstallTargetGenerator::Files const& files =
+ installTarget->GetFiles(this->Config);
+ if (files.From.empty()) {
+ return installer;
+ }
+
+ installer["type"] = "target";
+ installer["destination"] = installTarget->GetDestination(this->Config);
+ installer["targetId"] =
+ TargetId(installTarget->GetTarget(), this->TopBuild);
+ installer["targetIndex"] =
+ this->TargetIndexMap[installTarget->GetTarget()];
+
+ std::string fromDir = files.FromDir;
+ if (!fromDir.empty()) {
+ fromDir.push_back('/');
+ }
+
+ std::string toDir = files.ToDir;
+ if (!toDir.empty()) {
+ toDir.push_back('/');
+ }
+
+ Json::Value paths = Json::arrayValue;
+ for (size_t i = 0; i < files.From.size(); ++i) {
+ std::string const& fromPath = cmStrCat(fromDir, files.From[i]);
+ std::string const& toPath = cmStrCat(toDir, files.To[i]);
+ paths.append(this->DumpInstallerPath(this->TopBuild, fromPath, toPath));
+ }
+ installer["paths"] = std::move(paths);
+
+ if (installTarget->GetOptional()) {
+ installer["isOptional"] = true;
+ }
+
+ if (installTarget->IsImportLibrary()) {
+ installer["targetIsImportLibrary"] = true;
+ }
+
+ switch (files.NamelinkMode) {
+ case cmInstallTargetGenerator::NamelinkModeNone:
+ break;
+ case cmInstallTargetGenerator::NamelinkModeOnly:
+ installer["targetInstallNamelink"] = "only";
+ break;
+ case cmInstallTargetGenerator::NamelinkModeSkip:
+ installer["targetInstallNamelink"] = "skip";
+ break;
+ }
+
+ // FIXME: Parse FilePermissions to provide structured information.
+ // FIXME: Thread EXPORT name through from install() call.
+ } else if (auto* installFiles =
+ dynamic_cast<cmInstallFilesGenerator*>(gen)) {
+ std::vector<std::string> const& files =
+ installFiles->GetFiles(this->Config);
+ if (files.empty()) {
+ return installer;
+ }
+
+ installer["type"] = "file";
+ installer["destination"] = installFiles->GetDestination(this->Config);
+ Json::Value paths = Json::arrayValue;
+ std::string const& rename = installFiles->GetRename(this->Config);
+ if (!rename.empty() && files.size() == 1) {
+ paths.append(this->DumpInstallerPath(this->TopSource, files[0], rename));
+ } else {
+ for (std::string const& file : installFiles->GetFiles(this->Config)) {
+ paths.append(RelativeIfUnder(this->TopSource, file));
+ }
+ }
+ installer["paths"] = std::move(paths);
+ if (installFiles->GetOptional()) {
+ installer["isOptional"] = true;
+ }
+ // FIXME: Parse FilePermissions to provide structured information.
+ } else if (auto* installDir =
+ dynamic_cast<cmInstallDirectoryGenerator*>(gen)) {
+ std::vector<std::string> const& dirs =
+ installDir->GetDirectories(this->Config);
+ if (dirs.empty()) {
+ return installer;
+ }
+
+ installer["type"] = "directory";
+ installer["destination"] = installDir->GetDestination(this->Config);
+ Json::Value paths = Json::arrayValue;
+ for (std::string const& dir : dirs) {
+ if (cmHasLiteralSuffix(dir, "/")) {
+ paths.append(this->DumpInstallerPath(
+ this->TopSource, dir.substr(0, dir.size() - 1), "."));
+ } else {
+ paths.append(this->DumpInstallerPath(
+ this->TopSource, dir, cmSystemTools::GetFilenameName(dir)));
+ }
+ }
+ installer["paths"] = std::move(paths);
+ if (installDir->GetOptional()) {
+ installer["isOptional"] = true;
+ }
+ // FIXME: Parse FilePermissions, DirPermissions, and LiteralArguments.
+ // to provide structured information.
+ } else if (auto* installExport =
+ dynamic_cast<cmInstallExportGenerator*>(gen)) {
+ installer["type"] = "export";
+ installer["destination"] = installExport->GetDestination();
+ cmExportSet* exportSet = installExport->GetExportSet();
+ installer["exportName"] = exportSet->GetName();
+ installer["exportTargets"] = this->DumpInstallerExportTargets(exportSet);
+ Json::Value paths = Json::arrayValue;
+ paths.append(
+ RelativeIfUnder(this->TopBuild, installExport->GetMainImportFile()));
+ installer["paths"] = std::move(paths);
+ } else if (auto* installScript =
+ dynamic_cast<cmInstallScriptGenerator*>(gen)) {
+ if (installScript->IsCode()) {
+ installer["type"] = "code";
+ } else {
+ installer["type"] = "script";
+ installer["scriptFile"] = RelativeIfUnder(
+ this->TopSource, installScript->GetScript(this->Config));
+ }
+ } else if (auto* installImportedRuntimeArtifacts =
+ dynamic_cast<cmInstallImportedRuntimeArtifactsGenerator*>(
+ gen)) {
+ installer["type"] = "importedRuntimeArtifacts";
+ installer["destination"] =
+ installImportedRuntimeArtifacts->GetDestination(this->Config);
+ if (installImportedRuntimeArtifacts->GetOptional()) {
+ installer["isOptional"] = true;
+ }
+ } else if (auto* installRuntimeDependencySet =
+ dynamic_cast<cmInstallRuntimeDependencySetGenerator*>(gen)) {
+ installer["type"] = "runtimeDependencySet";
+ installer["destination"] =
+ installRuntimeDependencySet->GetDestination(this->Config);
+ std::string name(
+ installRuntimeDependencySet->GetRuntimeDependencySet()->GetName());
+ if (!name.empty()) {
+ installer["runtimeDependencySetName"] = name;
+ }
+ switch (installRuntimeDependencySet->GetDependencyType()) {
+ case cmInstallRuntimeDependencySetGenerator::DependencyType::Framework:
+ installer["runtimeDependencySetType"] = "framework";
+ break;
+ case cmInstallRuntimeDependencySetGenerator::DependencyType::Library:
+ installer["runtimeDependencySetType"] = "library";
+ break;
+ }
+ }
+
+ // Add fields common to all install generators.
+ installer["component"] = gen->GetComponent();
+ if (gen->GetExcludeFromAll()) {
+ installer["isExcludeFromAll"] = true;
+ }
+
+ if (gen->GetAllComponentsFlag()) {
+ installer["isForAllComponents"] = true;
+ }
+
+ this->AddBacktrace(installer, gen->GetBacktrace());
+
+ return installer;
+}
+
+Json::Value DirectoryObject::DumpInstallerExportTargets(cmExportSet* exp)
+{
+ Json::Value targets = Json::arrayValue;
+ for (auto const& targetExport : exp->GetTargetExports()) {
+ Json::Value target = Json::objectValue;
+ target["id"] = TargetId(targetExport->Target, this->TopBuild);
+ target["index"] = this->TargetIndexMap[targetExport->Target];
+ targets.append(std::move(target)); // NOLINT(*)
+ }
+ return targets;
+}
+
+Json::Value DirectoryObject::DumpInstallerPath(std::string const& top,
+ std::string const& fromPathIn,
+ std::string const& toPath)
+{
+ Json::Value installPath;
+
+ std::string fromPath = RelativeIfUnder(top, fromPathIn);
+
+ // If toPath is the last component of fromPath, use just fromPath.
+ if (toPath.find_first_of('/') == std::string::npos &&
+ cmHasSuffix(fromPath, toPath) &&
+ (fromPath.size() == toPath.size() ||
+ fromPath[fromPath.size() - toPath.size() - 1] == '/')) {
+ installPath = fromPath;
+ } else {
+ installPath = Json::objectValue;
+ installPath["from"] = fromPath;
+ installPath["to"] = toPath;
+ }
+
+ return installPath;
+}
+
Target::Target(cmGeneratorTarget* gt, std::string const& config)
: GT(gt)
, Config(config)
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 4a282384b..0ad59c7b5 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -990,50 +990,42 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args,
{
// Evaluate arguments.
std::string file;
- const char* oldRPath = nullptr;
- const char* newRPath = nullptr;
+ std::string oldRPath;
+ std::string newRPath;
bool removeEnvironmentRPath = false;
- enum Doing
- {
- DoingNone,
- DoingFile,
- DoingOld,
- DoingNew
- };
- Doing doing = DoingNone;
- for (unsigned int i = 1; i < args.size(); ++i) {
- if (args[i] == "OLD_RPATH") {
- doing = DoingOld;
- } else if (args[i] == "NEW_RPATH") {
- doing = DoingNew;
- } else if (args[i] == "FILE") {
- doing = DoingFile;
- } else if (args[i] == "INSTALL_REMOVE_ENVIRONMENT_RPATH") {
- removeEnvironmentRPath = true;
- } else if (doing == DoingFile) {
- file = args[i];
- doing = DoingNone;
- } else if (doing == DoingOld) {
- oldRPath = args[i].c_str();
- doing = DoingNone;
- } else if (doing == DoingNew) {
- newRPath = args[i].c_str();
- doing = DoingNone;
- } else {
- status.SetError(
- cmStrCat("RPATH_CHANGE given unknown argument ", args[i]));
- return 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);
+ 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 (file.empty()) {
status.SetError("RPATH_CHANGE not given FILE option.");
return false;
}
- if (!oldRPath) {
+ if (oldRPath.empty() &&
+ std::find(parsedArgs.begin(), parsedArgs.end(), "OLD_RPATH") ==
+ parsedArgs.end()) {
status.SetError("RPATH_CHANGE not given OLD_RPATH option.");
return false;
}
- if (!newRPath) {
+ if (newRPath.empty() &&
+ std::find(parsedArgs.begin(), parsedArgs.end(), "NEW_RPATH") ==
+ parsedArgs.end()) {
status.SetError("RPATH_CHANGE not given NEW_RPATH option.");
return false;
}
@@ -1065,28 +1057,85 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args,
return success;
}
+bool HandleRPathSetCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ // Evaluate arguments.
+ std::string file;
+ 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);
+ 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 (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()) {
+ status.SetError("RPATH_SET not given NEW_RPATH option.");
+ return false;
+ }
+ if (!cmSystemTools::FileExists(file, true)) {
+ status.SetError(
+ cmStrCat("RPATH_SET given FILE \"", file, "\" that does not exist."));
+ return false;
+ }
+ bool success = true;
+ cmFileTimes const ft(file);
+ std::string emsg;
+ bool 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",
+ emsg));
+ success = false;
+ }
+ if (success) {
+ if (changed) {
+ std::string message =
+ cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"');
+ status.GetMakefile().DisplayStatus(message, -1);
+ }
+ ft.Store(file);
+ }
+ return success;
+}
+
bool HandleRPathRemoveCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
// Evaluate arguments.
std::string file;
- enum Doing
- {
- DoingNone,
- DoingFile
- };
- Doing doing = DoingNone;
- for (unsigned int i = 1; i < args.size(); ++i) {
- if (args[i] == "FILE") {
- doing = DoingFile;
- } else if (doing == DoingFile) {
- file = args[i];
- doing = DoingNone;
- } else {
- status.SetError(
- cmStrCat("RPATH_REMOVE given unknown argument ", args[i]));
- return false;
- }
+ 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);
+ 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 (file.empty()) {
status.SetError("RPATH_REMOVE not given FILE option.");
@@ -1123,36 +1172,31 @@ bool HandleRPathCheckCommand(std::vector<std::string> const& args,
{
// Evaluate arguments.
std::string file;
- const char* rpath = nullptr;
- enum Doing
- {
- DoingNone,
- DoingFile,
- DoingRPath
- };
- Doing doing = DoingNone;
- for (unsigned int i = 1; i < args.size(); ++i) {
- if (args[i] == "RPATH") {
- doing = DoingRPath;
- } else if (args[i] == "FILE") {
- doing = DoingFile;
- } else if (doing == DoingFile) {
- file = args[i];
- doing = DoingNone;
- } else if (doing == DoingRPath) {
- rpath = args[i].c_str();
- doing = DoingNone;
- } else {
- status.SetError(
- cmStrCat("RPATH_CHECK given unknown argument ", args[i]));
- return false;
- }
+ 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);
+ 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 (file.empty()) {
status.SetError("RPATH_CHECK not given FILE option.");
return false;
}
- if (!rpath) {
+ if (rpath.empty() &&
+ std::find(parsedArgs.begin(), parsedArgs.end(), "RPATH") ==
+ parsedArgs.end()) {
status.SetError("RPATH_CHECK not given RPATH option.");
return false;
}
@@ -1246,9 +1290,12 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
struct Arguments
{
std::string BaseDirectory;
+ bool ExpandTilde = false;
};
- static auto const parser = cmArgumentParser<Arguments>{}.Bind(
- "BASE_DIRECTORY"_s, &Arguments::BaseDirectory);
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("BASE_DIRECTORY"_s, &Arguments::BaseDirectory)
+ .Bind("EXPAND_TILDE"_s, &Arguments::ExpandTilde);
std::vector<std::string> unparsedArguments;
std::vector<std::string> keywordsMissingValue;
@@ -1270,7 +1317,21 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
}
- cmCMakePath path(args[1]);
+ auto input = args[1];
+ if (arguments.ExpandTilde && !input.empty()) {
+ if (input[0] == '~' && (input.length() == 1 || input[1] == '/')) {
+ std::string home;
+ if (
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ cmSystemTools::GetEnv("USERPROFILE", home) ||
+#endif
+ cmSystemTools::GetEnv("HOME", home)) {
+ input.replace(0, 1, home);
+ }
+ }
+ }
+
+ cmCMakePath path(input, cmCMakePath::auto_format);
path = path.Absolute(arguments.BaseDirectory).Normal();
auto realPath = cmSystemTools::GetRealPath(path.GenericString());
@@ -1313,8 +1374,9 @@ bool HandleRelativePathCommand(std::vector<std::string> const& args,
bool HandleRename(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- if (args.size() != 3) {
- status.SetError("RENAME given incorrect number of arguments.");
+ if (args.size() < 3) {
+ status.SetError("RENAME must be called with at least two additional "
+ "arguments");
return false;
}
@@ -1330,21 +1392,148 @@ bool HandleRename(std::vector<std::string> const& args,
cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]);
}
- if (!cmSystemTools::RenameFile(oldname, newname)) {
- std::string err = cmSystemTools::GetLastSystemError();
- status.SetError(cmStrCat("RENAME failed to rename\n ", oldname,
- "\nto\n ", newname, "\nbecause: ", err, "\n"));
+ struct Arguments
+ {
+ bool NoReplace = false;
+ std::string Result;
+ };
+
+ static auto const parser = cmArgumentParser<Arguments>{}
+ .Bind("NO_REPLACE"_s, &Arguments::NoReplace)
+ .Bind("RESULT"_s, &Arguments::Result);
+
+ std::vector<std::string> unconsumedArgs;
+ Arguments const arguments =
+ parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs);
+ if (!unconsumedArgs.empty()) {
+ status.SetError("RENAME unknown argument:\n " + unconsumedArgs.front());
return false;
}
- return true;
+
+ std::string err;
+ switch (cmSystemTools::RenameFile(oldname, newname,
+ arguments.NoReplace
+ ? cmSystemTools::Replace::No
+ : cmSystemTools::Replace::Yes,
+ &err)) {
+ case cmSystemTools::RenameResult::Success:
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, "0");
+ }
+ return true;
+ case cmSystemTools::RenameResult::NoReplace:
+ if (!arguments.Result.empty()) {
+ err = "NO_REPLACE";
+ } else {
+ err = "path not replaced";
+ }
+ CM_FALLTHROUGH;
+ case cmSystemTools::RenameResult::Failure:
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, err);
+ return true;
+ }
+ break;
+ }
+ status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, "\nto\n ",
+ newname, "\nbecause: ", err, "\n"));
+ return false;
}
-bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse,
- cmExecutionStatus& status)
+bool HandleCopyFile(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
+ if (args.size() < 3) {
+ status.SetError("COPY_FILE must be called with at least two additional "
+ "arguments");
+ return false;
+ }
- std::string message;
+ // Compute full path for old and new names.
+ std::string oldname = args[1];
+ if (!cmsys::SystemTools::FileIsFullPath(oldname)) {
+ oldname =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]);
+ }
+ std::string newname = args[2];
+ if (!cmsys::SystemTools::FileIsFullPath(newname)) {
+ newname =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]);
+ }
+ struct Arguments
+ {
+ bool OnlyIfDifferent = false;
+ std::string Result;
+ };
+
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("ONLY_IF_DIFFERENT"_s, &Arguments::OnlyIfDifferent)
+ .Bind("RESULT"_s, &Arguments::Result);
+
+ std::vector<std::string> unconsumedArgs;
+ Arguments const arguments =
+ parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs);
+ if (!unconsumedArgs.empty()) {
+ status.SetError("COPY_FILE unknown argument:\n " +
+ unconsumedArgs.front());
+ return false;
+ }
+
+ bool result = true;
+ if (cmsys::SystemTools::FileIsDirectory(oldname)) {
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result,
+ "cannot copy a directory");
+ } else {
+ status.SetError(
+ cmStrCat("COPY_FILE cannot copy a directory\n ", oldname));
+ result = false;
+ }
+ return result;
+ }
+ if (cmsys::SystemTools::FileIsDirectory(newname)) {
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result,
+ "cannot copy to a directory");
+ } else {
+ status.SetError(
+ cmStrCat("COPY_FILE cannot copy to a directory\n ", newname));
+ result = false;
+ }
+ return result;
+ }
+
+ cmSystemTools::CopyWhen when;
+ if (arguments.OnlyIfDifferent) {
+ when = cmSystemTools::CopyWhen::OnlyIfDifferent;
+ } else {
+ when = cmSystemTools::CopyWhen::Always;
+ }
+
+ std::string err;
+ if (cmSystemTools::CopySingleFile(oldname, newname, when, &err) ==
+ cmSystemTools::CopyResult::Success) {
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, "0");
+ }
+ } else {
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, err);
+ } else {
+ status.SetError(cmStrCat("COPY_FILE failed to copy\n ", oldname,
+ "\nto\n ", newname, "\nbecause: ", err, "\n"));
+ result = false;
+ }
+ }
+
+ return result;
+}
+
+bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse,
+ cmExecutionStatus& status)
+{
for (std::string const& arg :
cmMakeRange(args).advance(1)) // Get rid of subcommand
{
@@ -2818,16 +3007,21 @@ bool HandleCreateLinkCommand(std::vector<std::string> const& args,
// Check if the command requires a symbolic link.
if (arguments.Symbolic) {
- completed = cmSystemTools::CreateSymlink(fileName, newFileName, &result);
+ completed = static_cast<bool>(
+ cmSystemTools::CreateSymlink(fileName, newFileName, &result));
} else {
- completed = cmSystemTools::CreateLink(fileName, newFileName, &result);
+ completed = static_cast<bool>(
+ cmSystemTools::CreateLink(fileName, newFileName, &result));
}
// Check if copy-on-error is enabled in the arguments.
if (!completed && arguments.CopyOnError) {
- completed = cmsys::SystemTools::CopyFileAlways(fileName, newFileName);
- if (!completed) {
- result = "Copy failed: " + cmSystemTools::GetLastSystemError();
+ cmsys::Status copied =
+ cmsys::SystemTools::CopyFileAlways(fileName, newFileName);
+ if (copied) {
+ completed = true;
+ } else {
+ result = "Copy failed: " + copied.GetString();
}
}
@@ -2850,11 +3044,10 @@ bool HandleCreateLinkCommand(std::vector<std::string> const& args,
bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- static const std::set<std::string> supportedPlatforms = { "Windows", "Linux",
- "Darwin" };
std::string platform =
status.GetMakefile().GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
- if (!supportedPlatforms.count(platform)) {
+ if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
+ platform)) {
status.SetError(
cmStrCat("GET_RUNTIME_DEPENDENCIES is not supported on system \"",
platform, "\""));
@@ -2882,6 +3075,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
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;
@@ -2891,6 +3085,9 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
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;
};
static auto const parser =
@@ -2900,6 +3097,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
&Arguments::UnresolvedDependenciesVar)
.Bind("CONFLICTING_DEPENDENCIES_PREFIX"_s,
&Arguments::ConflictingDependenciesPrefix)
+ .Bind("RPATH_PREFIX"_s, &Arguments::RPathPrefix)
.Bind("BUNDLE_EXECUTABLE"_s, &Arguments::BundleExecutable)
.Bind("EXECUTABLES"_s, &Arguments::Executables)
.Bind("LIBRARIES"_s, &Arguments::Libraries)
@@ -2908,7 +3106,10 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
.Bind("PRE_INCLUDE_REGEXES"_s, &Arguments::PreIncludeRegexes)
.Bind("PRE_EXCLUDE_REGEXES"_s, &Arguments::PreExcludeRegexes)
.Bind("POST_INCLUDE_REGEXES"_s, &Arguments::PostIncludeRegexes)
- .Bind("POST_EXCLUDE_REGEXES"_s, &Arguments::PostExcludeRegexes);
+ .Bind("POST_EXCLUDE_REGEXES"_s, &Arguments::PostExcludeRegexes)
+ .Bind("POST_INCLUDE_FILES"_s, &Arguments::PostIncludeFiles)
+ .Bind("POST_EXCLUDE_FILES"_s, &Arguments::PostExcludeFiles)
+ .Bind("POST_EXCLUDE_FILES_STRICT"_s, &Arguments::PostExcludeFilesStrict);
std::vector<std::string> unrecognizedArguments;
std::vector<std::string> keywordsMissingValues;
@@ -2922,14 +3123,19 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
return false;
}
- const std::vector<std::string> LIST_ARGS = { "DIRECTORIES",
- "EXECUTABLES",
- "LIBRARIES",
- "MODULES",
- "POST_EXCLUDE_REGEXES",
- "POST_INCLUDE_REGEXES",
- "PRE_EXCLUDE_REGEXES",
- "PRE_INCLUDE_REGEXES" };
+ 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) {
@@ -2942,7 +3148,10 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
cmRuntimeDependencyArchive archive(
status, parsedArgs.Directories, parsedArgs.BundleExecutable,
parsedArgs.PreIncludeRegexes, parsedArgs.PreExcludeRegexes,
- parsedArgs.PostIncludeRegexes, parsedArgs.PostExcludeRegexes);
+ parsedArgs.PostIncludeRegexes, parsedArgs.PostExcludeRegexes,
+ std::move(parsedArgs.PostIncludeFiles),
+ std::move(parsedArgs.PostExcludeFiles),
+ std::move(parsedArgs.PostExcludeFilesStrict));
if (!archive.Prepare()) {
cmSystemTools::SetFatalErrorOccured();
return false;
@@ -2971,6 +3180,11 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
if (unique) {
deps.push_back(firstPath);
+ if (!parsedArgs.RPathPrefix.empty()) {
+ status.GetMakefile().AddDefinition(
+ parsedArgs.RPathPrefix + "_" + firstPath,
+ cmJoin(archive.GetRPaths().at(firstPath), ";"));
+ }
} else if (!parsedArgs.ConflictingDependenciesPrefix.empty()) {
conflictingDeps.push_back(val.first);
std::vector<std::string> paths;
@@ -3569,6 +3783,7 @@ bool cmFileCommand(std::vector<std::string> const& args,
{ "GLOB_RECURSE"_s, HandleGlobRecurseCommand },
{ "MAKE_DIRECTORY"_s, HandleMakeDirectoryCommand },
{ "RENAME"_s, HandleRename },
+ { "COPY_FILE"_s, HandleCopyFile },
{ "REMOVE"_s, HandleRemove },
{ "REMOVE_RECURSE"_s, HandleRemoveRecurse },
{ "COPY"_s, HandleCopyCommand },
@@ -3576,6 +3791,7 @@ bool cmFileCommand(std::vector<std::string> const& args,
{ "DIFFERENT"_s, HandleDifferentCommand },
{ "RPATH_CHANGE"_s, HandleRPathChangeCommand },
{ "CHRPATH"_s, HandleRPathChangeCommand },
+ { "RPATH_SET"_s, HandleRPathSetCommand },
{ "RPATH_CHECK"_s, HandleRPathCheckCommand },
{ "RPATH_REMOVE"_s, HandleRPathRemoveCommand },
{ "READ_ELF"_s, HandleReadElfCommand },
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index bf52d7513..1038ac29e 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -9,7 +9,10 @@
#include <cmext/algorithm>
+#include "cmCMakePath.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmRange.h"
#include "cmSearchPath.h"
@@ -17,11 +20,13 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmake.h"
class cmExecutionStatus;
-cmFindBase::cmFindBase(cmExecutionStatus& status)
+cmFindBase::cmFindBase(std::string findCommandName, cmExecutionStatus& status)
: cmFindCommon(status)
+ , FindCommandName(std::move(findCommandName))
{
}
@@ -34,12 +39,15 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
// copy argsIn into args so it can be modified,
// in the process extract the DOC "documentation"
+ // and handle options NO_CACHE and ENV
size_t size = argsIn.size();
std::vector<std::string> args;
bool foundDoc = false;
for (unsigned int j = 0; j < size; ++j) {
if (foundDoc || argsIn[j] != "DOC") {
- if (argsIn[j] == "ENV") {
+ if (argsIn[j] == "NO_CACHE") {
+ this->StoreResultInCache = false;
+ } else if (argsIn[j] == "ENV") {
if (j + 1 < size) {
j++;
cmSystemTools::GetPath(args, argsIn[j].c_str());
@@ -63,11 +71,10 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
return false;
}
this->VariableName = args[0];
- if (this->CheckForVariableInCache()) {
- this->AlreadyInCache = true;
+ if (this->CheckForVariableDefined()) {
+ this->AlreadyDefined = true;
return true;
}
- this->AlreadyInCache = false;
// Find what search path locations have been enabled/disable
this->SelectDefaultSearchModes();
@@ -292,34 +299,159 @@ void cmFindBase::FillUserGuessPath()
paths.AddSuffixes(this->SearchPathSuffixes);
}
-bool cmFindBase::CheckForVariableInCache()
+bool cmFindBase::CheckForVariableDefined()
{
- if (cmProp cacheValue = this->Makefile->GetDefinition(this->VariableName)) {
+ if (cmProp value = this->Makefile->GetDefinition(this->VariableName)) {
cmState* state = this->Makefile->GetState();
cmProp cacheEntry = state->GetCacheEntryValue(this->VariableName);
- bool found = !cmIsNOTFOUND(*cacheValue);
+ bool found = !cmIsNOTFOUND(*value);
bool cached = cacheEntry != nullptr;
+ auto cacheType = cached ? state->GetCacheEntryType(this->VariableName)
+ : cmStateEnums::UNINITIALIZED;
+
+ if (cached && cacheType != cmStateEnums::UNINITIALIZED) {
+ this->VariableType = cacheType;
+ if (const auto* hs =
+ state->GetCacheEntryProperty(this->VariableName, "HELPSTRING")) {
+ this->VariableDocumentation = *hs;
+ }
+ }
+
if (found) {
// If the user specifies the entry on the command line without a
// type we should add the type and docstring but keep the
// original value. Tell the subclass implementations to do
// this.
- if (cached &&
- state->GetCacheEntryType(this->VariableName) ==
- cmStateEnums::UNINITIALIZED) {
+ if (cached && cacheType == cmStateEnums::UNINITIALIZED) {
this->AlreadyInCacheWithoutMetaInfo = true;
}
return true;
}
- if (cached) {
- cmProp hs =
- state->GetCacheEntryProperty(this->VariableName, "HELPSTRING");
- this->VariableDocumentation = hs ? *hs : "(none)";
- }
}
return false;
}
+void cmFindBase::NormalizeFindResult()
+{
+ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0125) ==
+ cmPolicies::NEW) {
+ // ensure the path returned by find_* command is absolute
+ const auto* existingValue =
+ this->Makefile->GetDefinition(this->VariableName);
+ std::string value;
+ if (!existingValue->empty()) {
+ value =
+ cmCMakePath(*existingValue, cmCMakePath::auto_format)
+ .Absolute(cmCMakePath(
+ this->Makefile->GetCMakeInstance()->GetCMakeWorkingDirectory()))
+ .Normal()
+ .GenericString();
+ // value = cmSystemTools::CollapseFullPath(*existingValue);
+ if (!cmSystemTools::FileExists(value, false)) {
+ value = *existingValue;
+ }
+ }
+
+ if (this->StoreResultInCache) {
+ // If the user specifies the entry on the command line without a
+ // type we should add the type and docstring but keep the original
+ // value.
+ if (value != *existingValue || this->AlreadyInCacheWithoutMetaInfo) {
+ this->Makefile->GetCMakeInstance()->AddCacheEntry(
+ this->VariableName, value.c_str(),
+ this->VariableDocumentation.c_str(), this->VariableType);
+ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) ==
+ cmPolicies::NEW) {
+ if (this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
+ this->Makefile->AddDefinition(this->VariableName, value);
+ }
+ } else {
+ // if there was a definition then remove it
+ // This is required to ensure same behavior as
+ // cmMakefile::AddCacheDefinition.
+ this->Makefile->RemoveDefinition(this->VariableName);
+ }
+ }
+ } else {
+ // ensure a normal variable is defined.
+ this->Makefile->AddDefinition(this->VariableName, value);
+ }
+ } else {
+ // If the user specifies the entry on the command line without a
+ // type we should add the type and docstring but keep the original
+ // value.
+ if (this->StoreResultInCache) {
+ if (this->AlreadyInCacheWithoutMetaInfo) {
+ this->Makefile->AddCacheDefinition(this->VariableName, "",
+ this->VariableDocumentation.c_str(),
+ this->VariableType);
+ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) ==
+ cmPolicies::NEW &&
+ this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
+ this->Makefile->AddDefinition(
+ this->VariableName,
+ *this->Makefile->GetCMakeInstance()->GetCacheDefinition(
+ this->VariableName));
+ }
+ }
+ } else {
+ // ensure a normal variable is defined.
+ this->Makefile->AddDefinition(
+ this->VariableName,
+ this->Makefile->GetSafeDefinition(this->VariableName));
+ }
+ }
+}
+
+void cmFindBase::StoreFindResult(const std::string& value)
+{
+ bool force =
+ this->Makefile->GetPolicyStatus(cmPolicies::CMP0125) == cmPolicies::NEW;
+ bool updateNormalVariable =
+ this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == cmPolicies::NEW;
+
+ if (!value.empty()) {
+ if (this->StoreResultInCache) {
+ this->Makefile->AddCacheDefinition(this->VariableName, value,
+ this->VariableDocumentation.c_str(),
+ this->VariableType, force);
+ if (updateNormalVariable &&
+ this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
+ this->Makefile->AddDefinition(this->VariableName, value);
+ }
+ } else {
+ this->Makefile->AddDefinition(this->VariableName, value);
+ }
+
+ return;
+ }
+
+ auto notFound = cmStrCat(this->VariableName, "-NOTFOUND");
+ if (this->StoreResultInCache) {
+ this->Makefile->AddCacheDefinition(this->VariableName, notFound,
+ this->VariableDocumentation.c_str(),
+ this->VariableType, force);
+ if (updateNormalVariable &&
+ this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
+ this->Makefile->AddDefinition(this->VariableName, notFound);
+ }
+ } else {
+ this->Makefile->AddDefinition(this->VariableName, notFound);
+ }
+
+ if (this->Required) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Could not find ", this->VariableName, " using the following ",
+ (this->FindCommandName == "find_file" ||
+ this->FindCommandName == "find_path"
+ ? "files"
+ : "names"),
+ ": ", cmJoin(this->Names, ", ")));
+ cmSystemTools::SetFatalErrorOccured();
+ }
+}
+
cmFindBaseDebugState::cmFindBaseDebugState(std::string commandName,
cmFindBase const* findBase)
: FindCommand(findBase)
diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h
index 57a40be9b..d197424db 100644
--- a/Source/cmFindBase.h
+++ b/Source/cmFindBase.h
@@ -9,6 +9,7 @@
#include <vector>
#include "cmFindCommon.h"
+#include "cmStateTypes.h"
class cmExecutionStatus;
@@ -21,7 +22,7 @@ class cmExecutionStatus;
class cmFindBase : public cmFindCommon
{
public:
- cmFindBase(cmExecutionStatus& status);
+ cmFindBase(std::string findCommandName, cmExecutionStatus& status);
virtual ~cmFindBase() = default;
/**
@@ -34,13 +35,20 @@ protected:
friend class cmFindBaseDebugState;
void ExpandPaths();
- // see if the VariableName is already set in the cache,
+ // see if the VariableName is already set,
// also copy the documentation from the cache to VariableDocumentation
// if it has documentation in the cache
- bool CheckForVariableInCache();
+ bool CheckForVariableDefined();
+
+ void NormalizeFindResult();
+ void StoreFindResult(const std::string& value);
+
+ // actual find command name
+ std::string FindCommandName;
// use by command during find
std::string VariableDocumentation;
+ cmStateEnums::CacheEntryType VariableType = cmStateEnums::UNINITIALIZED;
std::string VariableName;
std::vector<std::string> Names;
bool NamesPerDir = false;
@@ -49,8 +57,9 @@ protected:
// CMAKE_*_PATH CMAKE_SYSTEM_*_PATH FRAMEWORK|LIBRARY|INCLUDE|PROGRAM
std::string EnvironmentPath; // LIB,INCLUDE
- bool AlreadyInCache = false;
+ bool AlreadyDefined = false;
bool AlreadyInCacheWithoutMetaInfo = false;
+ bool StoreResultInCache = true;
bool Required = false;
diff --git a/Source/cmFindFileCommand.cxx b/Source/cmFindFileCommand.cxx
index 29a2bc49e..a88c1b10c 100644
--- a/Source/cmFindFileCommand.cxx
+++ b/Source/cmFindFileCommand.cxx
@@ -2,12 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindFileCommand.h"
+#include "cmStateTypes.h"
+
class cmExecutionStatus;
cmFindFileCommand::cmFindFileCommand(cmExecutionStatus& status)
- : cmFindPathCommand(status)
+ : cmFindPathCommand("find_file", status)
{
this->IncludeFileInPath = true;
+ this->VariableType = cmStateEnums::FILEPATH;
}
bool cmFindFile(std::vector<std::string> const& args,
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 49b1bd74b..0cbe63773 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -12,7 +12,6 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmMessageType.h"
#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
@@ -22,30 +21,26 @@
class cmExecutionStatus;
cmFindLibraryCommand::cmFindLibraryCommand(cmExecutionStatus& status)
- : cmFindBase(status)
+ : cmFindBase("find_library", status)
{
this->EnvironmentPath = "LIB";
this->NamesPerDirAllowed = true;
+ this->VariableDocumentation = "Path to a library.";
+ this->VariableType = cmStateEnums::FILEPATH;
}
// cmFindLibraryCommand
bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
{
this->DebugMode = this->ComputeIfDebugModeWanted();
- this->VariableDocumentation = "Path to a library.";
this->CMakePathName = "LIBRARY";
+
if (!this->ParseArguments(argsIn)) {
return false;
}
- if (this->AlreadyInCache) {
- // If the user specifies the entry on the command line without a
- // type we should add the type and docstring but keep the original
- // value.
- if (this->AlreadyInCacheWithoutMetaInfo) {
- this->Makefile->AddCacheDefinition(this->VariableName, "",
- this->VariableDocumentation.c_str(),
- cmStateEnums::FILEPATH);
- }
+
+ if (this->AlreadyDefined) {
+ this->NormalizeFindResult();
return true;
}
@@ -75,24 +70,7 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
}
std::string const library = this->FindLibrary();
- if (!library.empty()) {
- // Save the value in the cache
- this->Makefile->AddCacheDefinition(this->VariableName, library,
- this->VariableDocumentation.c_str(),
- cmStateEnums::FILEPATH);
- return true;
- }
- std::string notfound = this->VariableName + "-NOTFOUND";
- this->Makefile->AddCacheDefinition(this->VariableName, notfound,
- this->VariableDocumentation.c_str(),
- cmStateEnums::FILEPATH);
- if (this->Required) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "Could not find " + this->VariableName +
- " using the following names: " + cmJoin(this->Names, ", "));
- cmSystemTools::SetFatalErrorOccured();
- }
+ this->StoreFindResult(library);
return true;
}
@@ -208,7 +186,8 @@ std::string cmFindLibraryCommand::FindLibrary()
struct cmFindLibraryHelper
{
- cmFindLibraryHelper(cmMakefile* mf, cmFindBase const* findBase);
+ cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
+ cmFindBase const* findBase);
// Context information.
cmMakefile* Makefile;
@@ -280,11 +259,11 @@ struct cmFindLibraryHelper
};
};
-cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf,
+cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
cmFindBase const* base)
: Makefile(mf)
, DebugMode(base->DebugModeEnabled())
- , DebugSearches("find_library", base)
+ , DebugSearches(std::move(debugName), base)
{
this->GG = this->Makefile->GetGlobalGenerator();
@@ -374,7 +353,7 @@ void cmFindLibraryHelper::AddName(std::string const& name)
regex += "(\\.[0-9]+\\.[0-9]+)?";
}
regex += "$";
- entry.Regex.compile(regex.c_str());
+ entry.Regex.compile(regex);
this->Names.push_back(std::move(entry));
}
@@ -485,7 +464,7 @@ std::string cmFindLibraryCommand::FindNormalLibrary()
std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir()
{
// Search for all names in each directory.
- cmFindLibraryHelper helper(this->Makefile, this);
+ cmFindLibraryHelper helper(this->FindCommandName, this->Makefile, this);
for (std::string const& n : this->Names) {
helper.AddName(n);
}
@@ -502,7 +481,7 @@ std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir()
std::string cmFindLibraryCommand::FindNormalLibraryDirsPerName()
{
// Search the entire path for each name.
- cmFindLibraryHelper helper(this->Makefile, this);
+ cmFindLibraryHelper helper(this->FindCommandName, this->Makefile, this);
for (std::string const& n : this->Names) {
// Switch to searching for this name.
helper.SetName(n);
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 3719fe194..fba736eed 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -1138,6 +1138,11 @@ bool cmFindPackageCommand::FindConfig()
// We force the value since we do not get here if it was already set.
this->Makefile->AddCacheDefinition(this->Variable, init, help.c_str(),
cmStateEnums::PATH, true);
+ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) ==
+ cmPolicies::NEW &&
+ this->Makefile->IsNormalDefinitionSet(this->Variable)) {
+ this->Makefile->AddDefinition(this->Variable, init);
+ }
return found;
}
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 3fb082603..3d21167f7 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -2,70 +2,53 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindPathCommand.h"
+#include <utility>
+
#include "cmsys/Glob.hxx"
-#include "cmMakefile.h"
-#include "cmMessageType.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
class cmExecutionStatus;
-cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status)
- : cmFindBase(status)
+cmFindPathCommand::cmFindPathCommand(std::string findCommandName,
+ cmExecutionStatus& status)
+ : cmFindBase(std::move(findCommandName), status)
{
this->EnvironmentPath = "INCLUDE";
this->IncludeFileInPath = false;
+ this->VariableDocumentation = "Path to a file.";
+ this->VariableType = cmStateEnums::PATH;
+}
+cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status)
+ : cmFindPathCommand("find_path", status)
+{
}
// cmFindPathCommand
bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
{
this->DebugMode = this->ComputeIfDebugModeWanted();
- this->VariableDocumentation = "Path to a file.";
this->CMakePathName = "INCLUDE";
+
if (!this->ParseArguments(argsIn)) {
return false;
}
- if (this->AlreadyInCache) {
- // If the user specifies the entry on the command line without a
- // type we should add the type and docstring but keep the original
- // value.
- if (this->AlreadyInCacheWithoutMetaInfo) {
- this->Makefile->AddCacheDefinition(
- this->VariableName, "", this->VariableDocumentation.c_str(),
- (this->IncludeFileInPath ? cmStateEnums::FILEPATH
- : cmStateEnums::PATH));
- }
+
+ if (this->AlreadyDefined) {
+ this->NormalizeFindResult();
return true;
}
std::string result = this->FindHeader();
- if (!result.empty()) {
- this->Makefile->AddCacheDefinition(
- this->VariableName, result, this->VariableDocumentation.c_str(),
- (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH);
- return true;
- }
- this->Makefile->AddCacheDefinition(
- this->VariableName, this->VariableName + "-NOTFOUND",
- this->VariableDocumentation.c_str(),
- (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH);
- if (this->Required) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "Could not find " + this->VariableName +
- " using the following files: " + cmJoin(this->Names, ", "));
- cmSystemTools::SetFatalErrorOccured();
- }
+ this->StoreFindResult(result);
return true;
}
std::string cmFindPathCommand::FindHeader()
{
- std::string debug_name = this->IncludeFileInPath ? "find_file" : "find_path";
- cmFindBaseDebugState debug(debug_name, this);
+ cmFindBaseDebugState debug(this->FindCommandName, this);
std::string header;
if (this->SearchFrameworkFirst || this->SearchFrameworkOnly) {
header = this->FindFrameworkHeader(debug);
diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h
index 6101ea1c0..c7281f1f8 100644
--- a/Source/cmFindPathCommand.h
+++ b/Source/cmFindPathCommand.h
@@ -22,6 +22,7 @@ class cmFindPathCommand : public cmFindBase
{
public:
cmFindPathCommand(cmExecutionStatus& status);
+ cmFindPathCommand(std::string findCommandName, cmExecutionStatus& status);
bool InitialPass(std::vector<std::string> const& args);
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index c22462e84..1c87625e2 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -4,6 +4,7 @@
#include <algorithm>
#include <string>
+#include <utility>
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -20,8 +21,9 @@ class cmExecutionStatus;
struct cmFindProgramHelper
{
- cmFindProgramHelper(cmMakefile* makefile, cmFindBase const* base)
- : DebugSearches("find_program", base)
+ cmFindProgramHelper(std::string debugName, cmMakefile* makefile,
+ cmFindBase const* base)
+ : DebugSearches(std::move(debugName), base)
, Makefile(makefile)
, PolicyCMP0109(makefile->GetPolicyStatus(cmPolicies::CMP0109))
{
@@ -145,52 +147,31 @@ struct cmFindProgramHelper
};
cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status)
- : cmFindBase(status)
+ : cmFindBase("find_program", status)
{
this->NamesPerDirAllowed = true;
+ this->VariableDocumentation = "Path to a program.";
+ this->VariableType = cmStateEnums::FILEPATH;
}
// cmFindProgramCommand
bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn)
{
this->DebugMode = this->ComputeIfDebugModeWanted();
- this->VariableDocumentation = "Path to a program.";
this->CMakePathName = "PROGRAM";
+
// call cmFindBase::ParseArguments
if (!this->ParseArguments(argsIn)) {
return false;
}
- if (this->AlreadyInCache) {
- // If the user specifies the entry on the command line without a
- // type we should add the type and docstring but keep the original
- // value.
- if (this->AlreadyInCacheWithoutMetaInfo) {
- this->Makefile->AddCacheDefinition(this->VariableName, "",
- this->VariableDocumentation.c_str(),
- cmStateEnums::FILEPATH);
- }
+
+ if (this->AlreadyDefined) {
+ this->NormalizeFindResult();
return true;
}
std::string const result = this->FindProgram();
- if (!result.empty()) {
- // Save the value in the cache
- this->Makefile->AddCacheDefinition(this->VariableName, result,
- this->VariableDocumentation.c_str(),
- cmStateEnums::FILEPATH);
-
- return true;
- }
- this->Makefile->AddCacheDefinition(
- this->VariableName, this->VariableName + "-NOTFOUND",
- this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH);
- if (this->Required) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "Could not find " + this->VariableName +
- " using the following names: " + cmJoin(this->Names, ", "));
- cmSystemTools::SetFatalErrorOccured();
- }
+ this->StoreFindResult(result);
return true;
}
@@ -222,7 +203,7 @@ std::string cmFindProgramCommand::FindNormalProgram()
std::string cmFindProgramCommand::FindNormalProgramNamesPerDir()
{
// Search for all names in each directory.
- cmFindProgramHelper helper(this->Makefile, this);
+ cmFindProgramHelper helper(this->FindCommandName, this->Makefile, this);
for (std::string const& n : this->Names) {
helper.AddName(n);
}
@@ -245,7 +226,7 @@ std::string cmFindProgramCommand::FindNormalProgramNamesPerDir()
std::string cmFindProgramCommand::FindNormalProgramDirsPerName()
{
// Search the entire path for each name.
- cmFindProgramHelper helper(this->Makefile, this);
+ cmFindProgramHelper helper(this->FindCommandName, this->Makefile, this);
for (std::string const& n : this->Names) {
// Switch to searching for this name.
helper.SetName(n);
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index bcacb15f9..4845a6d09 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -17,6 +17,7 @@
#include <utility>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
@@ -25,7 +26,7 @@
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
+#include "cmPolicies.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -113,9 +114,11 @@ bool cmForEachFunctionBlocker::ReplayItems(
// At end of for each execute recorded commands
// store the old value
- std::string oldDef;
- if (cmProp d = mf.GetDefinition(this->Args.front())) {
- oldDef = *d;
+ cm::optional<std::string> oldDef;
+ if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) {
+ oldDef = mf.GetSafeDefinition(this->Args.front());
+ } else if (mf.IsNormalDefinitionSet(this->Args.front())) {
+ oldDef = *mf.GetDefinition(this->Args.front());
}
auto restore = false;
@@ -131,9 +134,14 @@ bool cmForEachFunctionBlocker::ReplayItems(
}
if (restore) {
- // restore the variable to its prior value
- mf.AddDefinition(this->Args.front(), oldDef);
+ if (oldDef) {
+ // restore the variable to its prior value
+ mf.AddDefinition(this->Args.front(), *oldDef);
+ } else {
+ mf.RemoveDefinition(this->Args.front());
+ }
}
+
return true;
}
@@ -185,10 +193,15 @@ bool cmForEachFunctionBlocker::ReplayZipLists(
assert("Sanity check" && iterationVars.size() == values.size());
// Store old values for iteration variables
- std::map<std::string, std::string> oldDefs;
+ std::map<std::string, cm::optional<std::string>> oldDefs;
for (auto i = 0u; i < values.size(); ++i) {
- if (cmProp d = mf.GetDefinition(iterationVars[i])) {
- oldDefs.emplace(iterationVars[i], *d);
+ const auto& varName = iterationVars[i];
+ if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) {
+ oldDefs.emplace(varName, mf.GetSafeDefinition(varName));
+ } else if (mf.IsNormalDefinitionSet(varName)) {
+ oldDefs.emplace(varName, *mf.GetDefinition(varName));
+ } else {
+ oldDefs.emplace(varName, cm::nullopt);
}
}
@@ -226,7 +239,11 @@ bool cmForEachFunctionBlocker::ReplayZipLists(
// Restore the variables to its prior value
if (restore) {
for (auto const& p : oldDefs) {
- mf.AddDefinition(p.first, p.second);
+ if (p.second) {
+ mf.AddDefinition(p.first, *p.second);
+ } else {
+ mf.RemoveDefinition(p.first);
+ }
}
}
return true;
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index 43f384ab0..06778b1eb 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -42,6 +42,11 @@ cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name,
#else
static_cast<void>(encoding);
#endif
+ if (encoding == codecvt::UTF8_WITH_BOM) {
+ // Write the BOM encoding header into the file
+ char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
+ this->write(magic, 3);
+ }
}
cmGeneratedFileStream::~cmGeneratedFileStream()
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index e40316e1a..c608bf940 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -14,6 +14,7 @@
#include <utility>
#include <cm/iterator>
+#include <cm/optional>
#include <cm/string_view>
#include <cm/vector>
#include <cmext/algorithm>
@@ -23,6 +24,7 @@
#include "cmsys/String.h"
#include "cmAlgorithms.h"
+#include "cmComputeLinkInformation.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
@@ -716,7 +718,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
static const CompilerIdNode cCompilerIdNode("C"), cxxCompilerIdNode("CXX"),
cudaCompilerIdNode("CUDA"), objcCompilerIdNode("OBJC"),
objcxxCompilerIdNode("OBJCXX"), fortranCompilerIdNode("Fortran"),
- ispcCompilerIdNode("ISPC");
+ hipCompilerIdNode("HIP"), ispcCompilerIdNode("ISPC");
struct CompilerVersionNode : public cmGeneratorExpressionNode
{
@@ -781,7 +783,8 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode
static const CompilerVersionNode cCompilerVersionNode("C"),
cxxCompilerVersionNode("CXX"), cudaCompilerVersionNode("CUDA"),
objcCompilerVersionNode("OBJC"), objcxxCompilerVersionNode("OBJCXX"),
- fortranCompilerVersionNode("Fortran"), ispcCompilerVersionNode("ISPC");
+ fortranCompilerVersionNode("Fortran"), ispcCompilerVersionNode("ISPC"),
+ hipCompilerVersionNode("HIP");
struct PlatformIdNode : public cmGeneratorExpressionNode
{
@@ -1627,8 +1630,8 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
type != cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "Objects of target \"" << tgtName
- << "\" referenced but is not an allowed library types (EXECUTABLE, "
- << "STATIC, SHARED, MODULE, OBJECT).";
+ << "\" referenced but is not one of the allowed target types "
+ << "(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT).";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
@@ -1679,7 +1682,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
// Create the cmSourceFile instances in the referencing directory.
cmMakefile* mf = context->LG->GetMakefile();
- for (std::string& o : objects) {
+ for (std::string const& o : objects) {
mf->AddTargetObject(tgtName, o);
}
@@ -1687,6 +1690,54 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
}
} targetObjectsNode;
+static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode
+{
+ TargetRuntimeDllsNode() {} // NOLINT(modernize-use-equals-default)
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ std::string tgtName = parameters.front();
+ cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
+ if (!gt) {
+ std::ostringstream e;
+ e << "Objects of target \"" << tgtName
+ << "\" referenced but no such target exists.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+ cmStateEnums::TargetType type = gt->GetType();
+ if (type != cmStateEnums::EXECUTABLE &&
+ type != cmStateEnums::SHARED_LIBRARY &&
+ type != cmStateEnums::MODULE_LIBRARY) {
+ std::ostringstream e;
+ e << "Objects of target \"" << tgtName
+ << "\" referenced but is not one of the allowed target types "
+ << "(EXECUTABLE, SHARED, MODULE).";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+
+ if (auto* cli = gt->GetLinkInformation(context->Config)) {
+ std::vector<std::string> dllPaths;
+ auto const& dlls = cli->GetRuntimeDLLs();
+
+ for (auto const& dll : dlls) {
+ if (auto loc = dll->MaybeGetLocation(context->Config)) {
+ dllPaths.emplace_back(*loc);
+ }
+ }
+
+ return cmJoin(dllPaths, ";");
+ }
+
+ return "";
+ }
+} targetRuntimeDllsNode;
+
static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
{
CompileFeaturesNode() {} // NOLINT(modernize-use-equals-default)
@@ -2547,6 +2598,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "OBJCXX_COMPILER_ID", &objcxxCompilerIdNode },
{ "CUDA_COMPILER_ID", &cudaCompilerIdNode },
{ "Fortran_COMPILER_ID", &fortranCompilerIdNode },
+ { "HIP_COMPILER_ID", &hipCompilerIdNode },
{ "VERSION_GREATER", &versionGreaterNode },
{ "VERSION_GREATER_EQUAL", &versionGreaterEqNode },
{ "VERSION_LESS", &versionLessNode },
@@ -2558,6 +2610,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "OBJC_COMPILER_VERSION", &objcCompilerVersionNode },
{ "OBJCXX_COMPILER_VERSION", &objcxxCompilerVersionNode },
{ "Fortran_COMPILER_VERSION", &fortranCompilerVersionNode },
+ { "HIP_COMPILER_VERSION", &hipCompilerVersionNode },
{ "PLATFORM_ID", &platformIdNode },
{ "COMPILE_FEATURES", &compileFeaturesNode },
{ "CONFIGURATION", &configurationNode },
@@ -2603,6 +2656,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "TARGET_EXISTS", &targetExistsNode },
{ "TARGET_NAME_IF_EXISTS", &targetNameIfExistsNode },
{ "TARGET_GENEX_EVAL", &targetGenexEvalNode },
+ { "TARGET_RUNTIME_DLLS", &targetRuntimeDllsNode },
{ "GENEX_EVAL", &genexEvalNode },
{ "BUILD_INTERFACE", &buildInterfaceNode },
{ "INSTALL_INTERFACE", &installInterfaceNode },
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index efac06a9d..f1ef130af 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -52,6 +52,11 @@
class cmMessenger;
+namespace {
+const cmsys::RegularExpression FrameworkRegularExpression(
+ "^(.*/)?([^/]*)\\.framework/(.*)$");
+}
+
template <>
cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
@@ -692,6 +697,7 @@ void cmGeneratorTarget::ClearSourcesCache()
this->SourcesAreContextDependent = Tribool::Indeterminate;
this->Objects.clear();
this->VisitedConfigsForObjects.clear();
+ this->LinkImplMap.clear();
}
void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before)
@@ -970,11 +976,11 @@ cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport(
std::string const& lang, const char* suffix) const
{
cmProp propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix));
- if (propertyValue == nullptr) {
+ if (!propertyValue) {
// Check if we should use the value set by another language.
if (lang == "OBJC") {
propertyValue = this->GetPropertyWithPairedLanguageSupport("C", suffix);
- } else if (lang == "OBJCXX" || lang == "CUDA") {
+ } else if (lang == "OBJCXX" || lang == "CUDA" || lang == "HIP") {
propertyValue =
this->GetPropertyWithPairedLanguageSupport("CXX", suffix);
}
@@ -1062,6 +1068,20 @@ const std::string& cmGeneratorTarget::GetLocation(
return location;
}
+cm::optional<std::string> cmGeneratorTarget::MaybeGetLocation(
+ std::string const& config) const
+{
+ cm::optional<std::string> location;
+ if (cmGeneratorTarget::ImportInfo const* imp = this->GetImportInfo(config)) {
+ if (!imp->Location.empty()) {
+ location = imp->Location;
+ }
+ } else {
+ location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
+ }
+ return location;
+}
+
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreBuildCommands()
const
{
@@ -1101,7 +1121,7 @@ void cmGeneratorTarget::AppendLanguageSideEffects(
std::map<std::string, std::set<cmGeneratorTarget const*>>& sideEffects) const
{
static const std::set<cm::string_view> LANGS_WITH_NO_SIDE_EFFECTS = {
- "C"_s, "CXX"_s, "OBJC"_s, "OBJCXX"_s, "ASM"_s, "CUDA"_s,
+ "C"_s, "CXX"_s, "OBJC"_s, "OBJCXX"_s, "ASM"_s, "CUDA"_s, "HIP"_s
};
for (auto const& lang : this->GetAllConfigCompileLanguages()) {
@@ -1215,6 +1235,20 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(
&dagChecker, result, excludeImported, language);
}
+ cmLinkImplementation const* impl = this->GetLinkImplementation(config);
+ if (impl != nullptr) {
+ auto runtimeEntries = impl->LanguageRuntimeLibraries.find(language);
+ if (runtimeEntries != impl->LanguageRuntimeLibraries.end()) {
+ for (auto const& lib : runtimeEntries->second) {
+ if (lib.Target) {
+ handleSystemIncludesDep(this->LocalGenerator, lib.Target, config,
+ this, &dagChecker, result, excludeImported,
+ language);
+ }
+ }
+ }
+ }
+
std::for_each(result.begin(), result.end(),
cmSystemTools::ConvertToUnixSlashes);
std::sort(result.begin(), result.end());
@@ -1454,31 +1488,80 @@ void AddLangSpecificImplicitIncludeDirectories(
}
}
+void addInterfaceEntry(cmGeneratorTarget const* headTarget,
+ std::string const& config, std::string const& prop,
+ std::string const& lang,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries,
+ bool usage_requirements_only,
+ std::vector<cmLinkImplItem> const& libraries)
+{
+ for (cmLinkImplItem const& lib : libraries) {
+ if (lib.Target) {
+ EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
+ // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
+ // caller's property and hand-evaluate it as if it were compiled.
+ // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+ cmGeneratorExpressionContext context(
+ headTarget->GetLocalGenerator(), config, false, headTarget, headTarget,
+ true, lib.Backtrace, lang);
+ cmExpandList(lib.Target->EvaluateInterfaceProperty(
+ prop, &context, dagChecker, usage_requirements_only),
+ ee.Values);
+ ee.ContextDependent = context.HadContextSensitiveCondition;
+ entries.Entries.emplace_back(std::move(ee));
+ }
+ }
+}
+
+// IncludeRuntimeInterface is used to break the cycle in computing
+// the necessary transitive dependencies of targets that can occur
+// now that we have implicit language runtime targets.
+//
+// To determine the set of languages that a target has we need to iterate
+// all the sources which includes transitive INTERFACE sources.
+// Therefore we can't determine what language runtimes are needed
+// for a target until after all sources are computed.
+//
+// Therefore while computing the applicable INTERFACE_SOURCES we
+// must ignore anything in LanguageRuntimeLibraries or we would
+// create a cycle ( INTERFACE_SOURCES requires LanguageRuntimeLibraries,
+// LanguageRuntimeLibraries requires INTERFACE_SOURCES).
+//
+enum class IncludeRuntimeInterface
+{
+ Yes,
+ No
+};
void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
std::string const& config, std::string const& prop,
std::string const& lang,
cmGeneratorExpressionDAGChecker* dagChecker,
EvaluatedTargetPropertyEntries& entries,
+ IncludeRuntimeInterface searchRuntime,
bool usage_requirements_only = true)
{
- if (cmLinkImplementationLibraries const* impl =
- headTarget->GetLinkImplementationLibraries(config)) {
- entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
- for (cmLinkImplItem const& lib : impl->Libraries) {
- if (lib.Target) {
- EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
- // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
- // caller's property and hand-evaluate it as if it were compiled.
- // Create a context as cmCompiledGeneratorExpression::Evaluate does.
- cmGeneratorExpressionContext context(
- headTarget->GetLocalGenerator(), config, false, headTarget,
- headTarget, true, lib.Backtrace, lang);
- cmExpandList(lib.Target->EvaluateInterfaceProperty(
- prop, &context, dagChecker, usage_requirements_only),
- ee.Values);
- ee.ContextDependent = context.HadContextSensitiveCondition;
- entries.Entries.emplace_back(std::move(ee));
+ if (searchRuntime == IncludeRuntimeInterface::Yes) {
+ if (cmLinkImplementation const* impl =
+ headTarget->GetLinkImplementation(config)) {
+ entries.HadContextSensitiveCondition =
+ impl->HadContextSensitiveCondition;
+
+ auto runtimeLibIt = impl->LanguageRuntimeLibraries.find(lang);
+ if (runtimeLibIt != impl->LanguageRuntimeLibraries.end()) {
+ addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
+ usage_requirements_only, runtimeLibIt->second);
}
+ addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
+ usage_requirements_only, impl->Libraries);
+ }
+ } else {
+ if (cmLinkImplementationLibraries const* impl =
+ headTarget->GetLinkImplementationLibraries(config)) {
+ entries.HadContextSensitiveCondition =
+ impl->HadContextSensitiveCondition;
+ addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
+ usage_requirements_only, impl->Libraries);
}
}
}
@@ -1636,7 +1719,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
// Collect INTERFACE_SOURCES of all direct link-dependencies.
EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(),
- &dagChecker, linkInterfaceSourcesEntries);
+ &dagChecker, linkInterfaceSourcesEntries,
+ IncludeRuntimeInterface::No, true);
std::vector<std::string>::size_type numFilesBefore = files.size();
bool contextDependentInterfaceSources = processSources(
this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources);
@@ -2243,8 +2327,16 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const
return cmSystemTools::GetFilenameName(info->Location);
}
// Use the soname given if any.
+ if (this->IsFrameworkOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (FrameworkRegularExpression.find(info->SOName.c_str(), match)) {
+ auto frameworkName = match.match(2);
+ auto fileName = match.match(3);
+ return cmStrCat(frameworkName, ".framework/", fileName);
+ }
+ }
if (cmHasLiteralPrefix(info->SOName, "@rpath/")) {
- return info->SOName.substr(6);
+ return info->SOName.substr(cmStrLen("@rpath/"));
}
return info->SOName;
}
@@ -3323,6 +3415,29 @@ void cmGeneratorTarget::AddISPCTargetFlags(std::string& flags) const
}
}
+void cmGeneratorTarget::AddHIPArchitectureFlags(std::string& flags) const
+{
+ const std::string& property = this->GetSafeProperty("HIP_ARCHITECTURES");
+
+ if (property.empty()) {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "HIP_ARCHITECTURES is empty for target \"" +
+ this->GetName() + "\".");
+ }
+
+ // If HIP_ARCHITECTURES is false we don't add any architectures.
+ if (cmIsOff(property)) {
+ return;
+ }
+
+ std::vector<std::string> options;
+ cmExpandList(property, options);
+
+ for (std::string& option : options) {
+ flags += " --offload-arch=" + option;
+ }
+}
+
void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const
{
std::string const& compiler =
@@ -3542,7 +3657,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
}
AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang,
- &dagChecker, entries);
+ &dagChecker, entries, IncludeRuntimeInterface::Yes);
if (this->Makefile->IsOn("APPLE")) {
if (cmLinkImplementationLibraries const* impl =
@@ -3767,7 +3882,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions(
this, config, language, &dagChecker, this->CompileOptionsEntries);
AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", language,
- &dagChecker, entries);
+ &dagChecker, entries, IncludeRuntimeInterface::Yes);
processOptions(this, entries, result, uniqueOptions, debugOptions,
"compile options", OptionsParse::Shell);
@@ -3809,7 +3924,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures(
this, config, std::string(), &dagChecker, this->CompileFeaturesEntries);
AddInterfaceEntries(this, config, "INTERFACE_COMPILE_FEATURES",
- std::string(), &dagChecker, entries);
+ std::string(), &dagChecker, entries,
+ IncludeRuntimeInterface::Yes);
processOptions(this, entries, result, uniqueFeatures, debugFeatures,
"compile features", OptionsParse::None);
@@ -3853,7 +3969,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions(
this, config, language, &dagChecker, this->CompileDefinitionsEntries);
AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", language,
- &dagChecker, entries);
+ &dagChecker, entries, IncludeRuntimeInterface::Yes);
if (!config.empty()) {
std::string configPropName =
@@ -3911,7 +4027,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders(
this, config, language, &dagChecker, this->PrecompileHeadersEntries);
AddInterfaceEntries(this, config, "INTERFACE_PRECOMPILE_HEADERS", language,
- &dagChecker, entries);
+ &dagChecker, entries, IncludeRuntimeInterface::Yes);
std::vector<BT<std::string>> list;
processOptions(this, entries, list, uniqueOptions, debugDefines,
@@ -4296,7 +4412,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
this, config, language, &dagChecker, this->LinkOptionsEntries);
AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language,
- &dagChecker, entries,
+ &dagChecker, entries, IncludeRuntimeInterface::Yes,
this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
processOptions(this, entries, result, uniqueOptions, debugOptions,
@@ -4555,7 +4671,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories(
this, config, language, &dagChecker, this->LinkDirectoriesEntries);
AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language,
- &dagChecker, entries,
+ &dagChecker, entries, IncludeRuntimeInterface::Yes,
this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
processLinkDirectories(this, entries, result, uniqueDirectories,
@@ -4594,7 +4710,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends(
}
}
AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language,
- &dagChecker, entries,
+ &dagChecker, entries, IncludeRuntimeInterface::Yes,
this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
processOptions(this, entries, result, uniqueOptions, false, "link depends",
@@ -4701,13 +4817,13 @@ bool cmGeneratorTarget::ComputeCompileFeatures(
cmStrCat(cmSystemTools::UpperCase(config), '-', language.first);
BTs<std::string> const* standardToCopy =
this->GetLanguageStandardProperty(language.second, config);
- if (standardToCopy != nullptr) {
+ if (standardToCopy) {
this->LanguageStandardMap[key] = *standardToCopy;
generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
} else {
cmProp defaultStandard = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT"));
- if (defaultStandard != nullptr) {
+ if (defaultStandard) {
this->LanguageStandardMap[key] = BTs<std::string>(*defaultStandard);
generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
}
@@ -4715,7 +4831,7 @@ bool cmGeneratorTarget::ComputeCompileFeatures(
// Custom updates for the CUDA standard.
if (generatorTargetLanguageStandard != nullptr &&
- language.first == "CUDA") {
+ (language.first == "CUDA")) {
if (generatorTargetLanguageStandard->Value == "98") {
this->LanguageStandardMap[key].Value = "03";
}
@@ -6229,29 +6345,28 @@ bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n,
return false;
}
-void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
- cmListFileBacktrace const& bt,
- std::vector<cmLinkItem>& items) const
+cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem(
+ std::string const& n, cmListFileBacktrace const& bt,
+ LookupLinkItemScope* scope) const
{
- cmLocalGenerator const* lg = this->LocalGenerator;
- for (std::string const& n : names) {
- if (this->IsLinkLookupScope(n, lg)) {
- continue;
- }
+ cm::optional<cmLinkItem> maybeItem;
+ if (this->IsLinkLookupScope(n, scope->LG)) {
+ return maybeItem;
+ }
- std::string name = this->CheckCMP0004(n);
- if (name == this->GetName() || name.empty()) {
- continue;
- }
- items.push_back(this->ResolveLinkItem(name, bt, lg));
+ std::string name = this->CheckCMP0004(n);
+ if (name == this->GetName() || name.empty()) {
+ return maybeItem;
}
+ maybeItem = this->ResolveLinkItem(name, bt, scope->LG);
+ return maybeItem;
}
void cmGeneratorTarget::ExpandLinkItems(
std::string const& prop, std::string const& value, std::string const& config,
cmGeneratorTarget const* headTarget, bool usage_requirements_only,
- std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition,
- bool& hadContextSensitiveCondition,
+ std::vector<cmLinkItem>& items, std::vector<cmLinkItem>& objects,
+ bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition,
bool& hadLinkLanguageSensitiveCondition) const
{
// Keep this logic in sync with ComputeLinkImplementationLibraries.
@@ -6265,10 +6380,30 @@ void cmGeneratorTarget::ExpandLinkItems(
}
std::vector<std::string> libs;
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+ cge->SetEvaluateForBuildsystem(true);
cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget,
&dagChecker, this, headTarget->LinkerLanguage),
libs);
- this->LookupLinkItems(libs, cge->GetBacktrace(), items);
+ cmMakefile const* mf = this->LocalGenerator->GetMakefile();
+ LookupLinkItemScope scope{ this->LocalGenerator };
+ for (std::string const& lib : libs) {
+ if (cm::optional<cmLinkItem> maybeItem =
+ this->LookupLinkItem(lib, cge->GetBacktrace(), &scope)) {
+ if (!maybeItem->Target) {
+ // Report explicitly linked object files separately.
+ std::string const& maybeObj = maybeItem->AsStr();
+ if (cmSystemTools::FileIsFullPath(maybeObj)) {
+ cmSourceFile const* sf =
+ mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
+ if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
+ objects.emplace_back(std::move(*maybeItem));
+ continue;
+ }
+ }
+ }
+ items.emplace_back(std::move(*maybeItem));
+ }
+ }
hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
hadContextSensitiveCondition = cge->GetHadContextSensitiveCondition();
hadLinkLanguageSensitiveCondition =
@@ -6319,6 +6454,7 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
iface.AllDone = true;
if (iface.Exists) {
this->ComputeLinkInterface(config, iface, head, secondPass);
+ this->ComputeLinkInterfaceRuntimeLibraries(config, iface);
}
}
@@ -6446,9 +6582,19 @@ std::string cmGeneratorTarget::GetDirectory(
const std::string& config, cmStateEnums::ArtifactType artifact) const
{
if (this->IsImported()) {
+ auto fullPath = this->Target->ImportedGetFullPath(config, artifact);
+ if (this->IsFrameworkOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (FrameworkRegularExpression.find(fullPath.c_str(), match)) {
+ auto path = match.match(1);
+ if (!path.empty()) {
+ path.erase(path.length() - 1);
+ }
+ return path;
+ }
+ }
// Return the directory from which the target is imported.
- return cmSystemTools::GetFilenamePath(
- this->Target->ImportedGetFullPath(config, artifact));
+ return cmSystemTools::GetFilenamePath(fullPath);
}
if (OutputInfo const* info = this->GetOutputInfo(config)) {
// Return the directory in which the target will be built.
@@ -6757,13 +6903,13 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
return;
}
iface.Exists = true;
- iface.Explicit = cmp0022NEW || explicitLibraries != nullptr;
+ iface.Explicit = cmp0022NEW || explicitLibraries;
if (explicitLibraries) {
// The interface libraries have been explicitly set.
this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config,
headTarget, usage_requirements_only, iface.Libraries,
- iface.HadHeadSensitiveCondition,
+ iface.Objects, iface.HadHeadSensitiveCondition,
iface.HadContextSensitiveCondition,
iface.HadLinkLanguageSensitiveCondition);
return;
@@ -6787,6 +6933,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
// Compare the link implementation fallback link interface to the
// preferred new link interface property and warn if different.
std::vector<cmLinkItem> ifaceLibs;
+ std::vector<cmLinkItem> ifaceObjects;
static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
if (cmProp newExplicitLibraries = this->GetProperty(newProp)) {
bool hadHeadSensitiveConditionDummy = false;
@@ -6794,7 +6941,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
bool hadLinkLanguageSensitiveConditionDummy = false;
this->ExpandLinkItems(newProp, *newExplicitLibraries, config,
headTarget, usage_requirements_only, ifaceLibs,
- hadHeadSensitiveConditionDummy,
+ ifaceObjects, hadHeadSensitiveConditionDummy,
hadContextSensitiveConditionDummy,
hadLinkLanguageSensitiveConditionDummy);
}
@@ -6831,6 +6978,83 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
}
}
+namespace {
+
+template <typename ReturnType>
+ReturnType constructItem(cmGeneratorTarget* target,
+ cmListFileBacktrace const& bt);
+
+template <>
+inline cmLinkImplItem constructItem(cmGeneratorTarget* target,
+ cmListFileBacktrace const& bt)
+{
+ return cmLinkImplItem(cmLinkItem(target, false, bt), false);
+}
+
+template <>
+inline cmLinkItem constructItem(cmGeneratorTarget* target,
+ cmListFileBacktrace const& bt)
+{
+ return cmLinkItem(target, false, bt);
+}
+
+template <typename ValueType>
+std::vector<ValueType> computeImplicitLanguageTargets(
+ std::string const& lang, std::string const& config,
+ cmGeneratorTarget const* currentTarget)
+{
+ cmListFileBacktrace bt;
+ std::vector<ValueType> result;
+ cmLocalGenerator* lg = currentTarget->GetLocalGenerator();
+
+ std::string const& runtimeLibrary =
+ currentTarget->GetRuntimeLinkLibrary(lang, config);
+ if (cmProp runtimeLinkOptions = currentTarget->Makefile->GetDefinition(
+ "CMAKE_" + lang + "_RUNTIME_LIBRARIES_" + runtimeLibrary)) {
+ std::vector<std::string> libsVec = cmExpandedList(*runtimeLinkOptions);
+ result.reserve(libsVec.size());
+
+ for (std::string const& i : libsVec) {
+ cmGeneratorTarget::TargetOrString resolved =
+ currentTarget->ResolveTargetReference(i, lg);
+ if (resolved.Target) {
+ result.emplace_back(constructItem<ValueType>(resolved.Target, bt));
+ }
+ }
+ }
+
+ return result;
+}
+}
+
+void cmGeneratorTarget::ComputeLinkInterfaceRuntimeLibraries(
+ const std::string& config, cmOptionalLinkInterface& iface) const
+{
+ for (std::string const& lang : iface.Languages) {
+ if ((lang == "CUDA" || lang == "HIP") &&
+ iface.LanguageRuntimeLibraries.find(lang) ==
+ iface.LanguageRuntimeLibraries.end()) {
+ auto implicitTargets =
+ computeImplicitLanguageTargets<cmLinkItem>(lang, config, this);
+ iface.LanguageRuntimeLibraries[lang] = std::move(implicitTargets);
+ }
+ }
+}
+
+void cmGeneratorTarget::ComputeLinkImplementationRuntimeLibraries(
+ const std::string& config, cmOptionalLinkImplementation& impl) const
+{
+ for (std::string const& lang : impl.Languages) {
+ if ((lang == "CUDA" || lang == "HIP") &&
+ impl.LanguageRuntimeLibraries.find(lang) ==
+ impl.LanguageRuntimeLibraries.end()) {
+ auto implicitTargets =
+ computeImplicitLanguageTargets<cmLinkImplItem>(lang, config, this);
+ impl.LanguageRuntimeLibraries[lang] = std::move(implicitTargets);
+ }
+ }
+}
+
const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
const std::string& config, cmGeneratorTarget const* headTarget,
bool usage_requirements_only, bool secondPass) const
@@ -6862,11 +7086,17 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
cmExpandList(info->Languages, iface.Languages);
this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
headTarget, usage_requirements_only, iface.Libraries,
- iface.HadHeadSensitiveCondition,
+ iface.Objects, iface.HadHeadSensitiveCondition,
iface.HadContextSensitiveCondition,
iface.HadLinkLanguageSensitiveCondition);
std::vector<std::string> deps = cmExpandedList(info->SharedDeps);
- this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps);
+ LookupLinkItemScope scope{ this->LocalGenerator };
+ for (std::string const& dep : deps) {
+ if (cm::optional<cmLinkItem> maybeItem =
+ this->LookupLinkItem(dep, cmListFileBacktrace(), &scope)) {
+ iface.SharedDeps.emplace_back(std::move(*maybeItem));
+ }
+ }
}
return &iface;
@@ -7090,6 +7320,7 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
if (!impl.LanguagesDone) {
impl.LanguagesDone = true;
this->ComputeLinkImplementationLanguages(config, impl);
+ this->ComputeLinkImplementationRuntimeLibraries(config, impl);
}
return &impl;
}
@@ -7379,6 +7610,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
cmGeneratorTarget const* head) const
{
cmLocalGenerator const* lg = this->LocalGenerator;
+ cmMakefile const* mf = lg->GetMakefile();
cmStringRange entryRange = this->Target->GetLinkImplementationEntries();
cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces();
cmBacktraceRange::const_iterator btIt = btRange.begin();
@@ -7392,6 +7624,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
nullptr);
cmGeneratorExpression ge(*btIt);
std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
+ cge->SetEvaluateForBuildsystem(true);
std::string const& evaluated =
cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr,
this->LinkerLanguage);
@@ -7452,8 +7685,21 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
}
// The entry is meant for this configuration.
- impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt, lg),
- evaluated != *le);
+ cmLinkItem item = this->ResolveLinkItem(name, *btIt, lg);
+ if (!item.Target) {
+ // Report explicitly linked object files separately.
+ std::string const& maybeObj = item.AsStr();
+ if (cmSystemTools::FileIsFullPath(maybeObj)) {
+ cmSourceFile const* sf =
+ mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
+ if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
+ impl.Objects.emplace_back(std::move(item));
+ continue;
+ }
+ }
+ }
+
+ impl.Libraries.emplace_back(std::move(item), evaluated != *le);
}
std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 8fe70abfc..6d2aa85ed 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -14,6 +14,8 @@
#include <utility>
#include <vector>
+#include <cm/optional>
+
#include "cmLinkItem.h"
#include "cmListFileCache.h"
#include "cmPolicies.h"
@@ -50,6 +52,9 @@ public:
bool CanCompileSources() const;
const std::string& GetLocation(const std::string& config) const;
+ /** Get the full path to the target's main artifact, if known. */
+ cm::optional<std::string> MaybeGetLocation(std::string const& config) const;
+
std::vector<cmCustomCommand> const& GetPreBuildCommands() const;
std::vector<cmCustomCommand> const& GetPreLinkCommands() const;
std::vector<cmCustomCommand> const& GetPostBuildCommands() const;
@@ -454,6 +459,8 @@ public:
void AddCUDAArchitectureFlags(std::string& flags) const;
void AddCUDAToolkitFlags(std::string& flags) const;
+ void AddHIPArchitectureFlags(std::string& flags) const;
+
void AddISPCTargetFlags(std::string& flags) const;
std::string GetFeatureSpecificLinkRuleVariable(
@@ -1031,12 +1038,17 @@ private:
const cmGeneratorTarget* headTarget,
bool usage_requirements_only,
std::vector<cmLinkItem>& items,
+ std::vector<cmLinkItem>& objects,
bool& hadHeadSensitiveCondition,
bool& hadContextSensitiveCondition,
bool& hadLinkLanguageSensitiveCondition) const;
- void LookupLinkItems(std::vector<std::string> const& names,
- cmListFileBacktrace const& bt,
- std::vector<cmLinkItem>& items) const;
+ struct LookupLinkItemScope
+ {
+ cmLocalGenerator const* LG;
+ };
+ cm::optional<cmLinkItem> LookupLinkItem(std::string const& n,
+ cmListFileBacktrace const& bt,
+ LookupLinkItemScope* scope) const;
std::vector<BT<std::string>> GetSourceFilePaths(
std::string const& config) const;
@@ -1104,6 +1116,12 @@ private:
cmProp GetPropertyWithPairedLanguageSupport(std::string const& lang,
const char* suffix) const;
+ void ComputeLinkImplementationRuntimeLibraries(
+ const std::string& config, cmOptionalLinkImplementation& impl) const;
+
+ void ComputeLinkInterfaceRuntimeLibraries(
+ const std::string& config, cmOptionalLinkInterface& iface) const;
+
public:
const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
const std::string& config) const;
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index ed5bff5ff..32238e4bd 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -159,13 +159,11 @@ void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout,
const std::string& config)
{
std::string outpath;
- std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory();
if (this->TagType != GhsMultiGpj::SUBPROJECT) {
// set target binary file destination
outpath = this->GeneratorTarget->GetDirectory(config);
- outpath =
- this->LocalGenerator->MaybeConvertToRelativePath(rootpath, outpath);
+ outpath = this->LocalGenerator->MaybeRelativeToCurBinDir(outpath);
/* clang-format off */
fout << " :binDirRelative=\"" << outpath << "\"\n"
" -o \"" << this->TargetNameReal << "\"\n";
@@ -369,7 +367,6 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
// if the command specified a working directory use it.
std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory();
- std::string currentBinDir = dir;
std::string workingDir = ccg.GetWorkingDirectory();
if (!workingDir.empty()) {
dir = workingDir;
@@ -427,8 +424,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
// working directory will be the start-output directory.
bool had_slash = cmd.find('/') != std::string::npos;
if (workingDir.empty()) {
- cmd =
- this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, cmd);
+ cmd = this->LocalGenerator->MaybeRelativeToCurBinDir(cmd);
}
bool has_slash = cmd.find('/') != std::string::npos;
if (had_slash && !has_slash) {
@@ -710,7 +706,7 @@ void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
std::ostream& fout, const cmSourceFile* sourceFile)
{
cmProp rawLangProp = sourceFile->GetProperty("LANGUAGE");
- if (nullptr != rawLangProp) {
+ if (rawLangProp) {
std::string sourceLangProp(*rawLangProp);
std::string const& extension = sourceFile->GetExtension();
if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) {
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 996fcff1d..b7bac9c13 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -30,7 +30,7 @@ cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator(cmake* cm)
/*
* Borland Make does not support long line depend rule, as we have tested
* generate one source file includes 40000 header files, and generate
- * depend.make in one line(use line continued tag), and error occured:
+ * depend.make in one line(use line continued tag), and error occurred:
* ** Fatal CMakeFiles\main.dir\depend.make 1224: Rule line too long **
* we disable long line dependencies rule generation for Borland make
*/
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index ab76260f9..919377812 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -36,6 +36,7 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmInstallGenerator.h"
+#include "cmInstallRuntimeDependencySet.h"
#include "cmLinkLineComputer.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
@@ -2077,7 +2078,7 @@ bool cmGlobalGenerator::Open(const std::string& bindir,
std::string cmGlobalGenerator::GenerateCMakeBuildCommand(
const std::string& target, const std::string& config,
- const std::string& native, bool ignoreErrors)
+ const std::string& parallel, const std::string& native, bool ignoreErrors)
{
std::string makeCommand = cmSystemTools::GetCMakeCommand();
makeCommand =
@@ -2087,6 +2088,11 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand(
makeCommand += config;
makeCommand += "\"";
}
+ if (!parallel.empty()) {
+ makeCommand += " --parallel \"";
+ makeCommand += parallel;
+ makeCommand += "\"";
+ }
if (!target.empty()) {
makeCommand += " --target \"";
makeCommand += target;
@@ -2255,7 +2261,7 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
// Check whether the genex expansion of the property agrees in all
// configurations.
- if (trueCount && falseCount) {
+ if (trueCount > 0 && falseCount > 0) {
std::ostringstream e;
e << "The EXCLUDE_FROM_ALL property of target \"" << target->GetName()
<< "\" varies by configuration. This is not supported by the \""
@@ -3022,10 +3028,8 @@ void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
}
// Shorten the output name (in expected use case).
- cmStateDirectory cmDir =
- this->GetMakefiles()[0]->GetStateSnapshot().GetDirectory();
- std::string fname = cmDir.ConvertToRelPathIfNotContained(
- this->GetMakefiles()[0]->GetState()->GetBinaryDirectory(), outputs[0]);
+ std::string fname =
+ this->LocalGenerators[0]->MaybeRelativeToTopBinDir(outputs[0]);
// Associate the hash with this output.
this->RuleHashes[fname] = hash;
@@ -3329,3 +3333,26 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile()
return true;
}
+
+cmInstallRuntimeDependencySet*
+cmGlobalGenerator::CreateAnonymousRuntimeDependencySet()
+{
+ auto set = cm::make_unique<cmInstallRuntimeDependencySet>();
+ auto* retval = set.get();
+ this->RuntimeDependencySets.push_back(std::move(set));
+ return retval;
+}
+
+cmInstallRuntimeDependencySet* cmGlobalGenerator::GetNamedRuntimeDependencySet(
+ const std::string& name)
+{
+ auto it = this->RuntimeDependencySetsByName.find(name);
+ if (it == this->RuntimeDependencySetsByName.end()) {
+ auto set = cm::make_unique<cmInstallRuntimeDependencySet>(name);
+ it =
+ this->RuntimeDependencySetsByName.insert(std::make_pair(name, set.get()))
+ .first;
+ this->RuntimeDependencySets.push_back(std::move(set));
+ }
+ return it->second;
+}
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 590de268c..147146e13 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -42,6 +42,7 @@ class cmDirectoryId;
class cmExportBuildFileGenerator;
class cmExternalMakefileProjectGenerator;
class cmGeneratorTarget;
+class cmInstallRuntimeDependencySet;
class cmLinkLineComputer;
class cmLocalGenerator;
class cmMakefile;
@@ -249,9 +250,13 @@ public:
virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const;
- /** Generate a "cmake --build" call for a given target and config. */
+ /**
+ * Generate a "cmake --build" call for a given target, config and parallel
+ * level.
+ */
std::string GenerateCMakeBuildCommand(const std::string& target,
const std::string& config,
+ const std::string& parallel,
const std::string& native,
bool ignoreErrors);
@@ -524,6 +529,11 @@ public:
std::string NewDeferId();
+ cmInstallRuntimeDependencySet* CreateAnonymousRuntimeDependencySet();
+
+ cmInstallRuntimeDependencySet* GetNamedRuntimeDependencySet(
+ const std::string& name);
+
protected:
// for a project collect all its targets by following depend
// information, and also collect all the targets
@@ -743,6 +753,11 @@ private:
std::unordered_set<std::string> GeneratedFiles;
+ std::vector<std::unique_ptr<cmInstallRuntimeDependencySet>>
+ RuntimeDependencySets;
+ std::map<std::string, cmInstallRuntimeDependencySet*>
+ RuntimeDependencySetsByName;
+
#if !defined(CMAKE_BOOTSTRAP)
// Pool of file locks
cmFileLockPool FileLockPool;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 172cf3fc0..7cf3e9363 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -375,7 +375,7 @@ void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout,
}
void cmGlobalGhsMultiGenerator::WriteProjectLine(
- std::ostream& fout, cmGeneratorTarget const* target, cmLocalGenerator* root,
+ std::ostream& fout, cmGeneratorTarget const* target,
std::string& rootBinaryDir)
{
cmProp projName = target->GetProperty("GENERATOR_FILE_NAME");
@@ -383,7 +383,7 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine(
if (projName && projType) {
cmLocalGenerator* lg = target->GetLocalGenerator();
std::string dir = lg->GetCurrentBinaryDirectory();
- dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir);
+ dir = cmSystemTools::ForceToRelativePath(rootBinaryDir, dir);
if (dir == ".") {
dir.clear();
} else {
@@ -433,7 +433,7 @@ void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root)
target->GetName(), "] had a cycle.\n"));
} else {
for (auto& tgt : build) {
- this->WriteProjectLine(fbld, tgt, root, rootBinaryDir);
+ this->WriteProjectLine(fbld, tgt, rootBinaryDir);
}
}
fbld.Close();
@@ -490,7 +490,7 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget(
target->GetType() == cmStateEnums::SHARED_LIBRARY) {
continue;
}
- this->WriteProjectLine(fbld, target, root, rootBinaryDir);
+ this->WriteProjectLine(fbld, target, rootBinaryDir);
}
}
fbld.Close();
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index 7753b311b..bd08301fd 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -103,7 +103,7 @@ private:
void WriteSubProjects(std::ostream& fout, std::string& all_target);
void WriteTargets(cmLocalGenerator* root);
void WriteProjectLine(std::ostream& fout, cmGeneratorTarget const* target,
- cmLocalGenerator* root, std::string& rootBinaryDir);
+ std::string& rootBinaryDir);
void WriteCustomRuleBOD(std::ostream& fout);
void WriteCustomTargetBOD(std::ostream& fout);
void WriteAllTarget(cmLocalGenerator* root,
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index 36f583f01..f08b1da36 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -2,7 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalNMakeMakefileGenerator.h"
+#include "cmsys/RegularExpression.hxx"
+
#include "cmDocumentationEntry.h"
+#include "cmDuration.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmState.h"
@@ -34,6 +37,42 @@ void cmGlobalNMakeMakefileGenerator::EnableLanguage(
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
+bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf)
+{
+ if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
+ return false;
+ }
+ if (cmProp nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
+ std::vector<std::string> command{ *nmakeCommand, "-?" };
+ std::string out;
+ std::string err;
+ if (!cmSystemTools::RunSingleCommand(command, &out, &err, nullptr, nullptr,
+ cmSystemTools::OUTPUT_NONE,
+ cmDuration(30))) {
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("Running\n '", cmJoin(command, "' '"),
+ "'\n"
+ "failed with:\n ",
+ err));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ cmsys::RegularExpression regex(
+ "Program Maintenance Utility Version ([1-9][0-9.]+)");
+ if (regex.find(err)) {
+ this->NMakeVersion = regex.match(1);
+ this->CheckNMakeFeatures();
+ }
+ }
+ return true;
+}
+
+void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures()
+{
+ this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->NMakeVersion.c_str(), "9");
+}
+
void cmGlobalNMakeMakefileGenerator::GetDocumentation(
cmDocumentationEntry& entry)
{
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index abe64ff96..402b89fda 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -31,7 +31,7 @@ public:
/** Get encoding used by generator for makefile files */
codecvt::Encoding GetMakefileEncoding() const override
{
- return codecvt::ANSI;
+ return this->NMakeSupportsUTF8 ? codecvt::UTF8_WITH_BOM : codecvt::ANSI;
}
/** Get the documentation entry for this generator. */
@@ -55,6 +55,11 @@ protected:
void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
private:
+ bool NMakeSupportsUTF8 = false;
+ std::string NMakeVersion;
+ bool FindMakeProgram(cmMakefile* mf) override;
+ void CheckNMakeFeatures();
+
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
const char* envVar) const override;
};
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index c502fb85a..963118fd6 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -6,9 +6,12 @@
#include <cctype>
#include <cstdio>
#include <sstream>
+#include <utility>
#include <cm/iterator>
#include <cm/memory>
+#include <cm/optional>
+#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/memory>
@@ -214,22 +217,41 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
{
// Write explicit outputs
for (std::string const& output : build.Outputs) {
- buildStr += cmStrCat(' ', this->EncodePath(output));
+ buildStr = cmStrCat(buildStr, ' ', this->EncodePath(output));
if (this->ComputingUnknownDependencies) {
this->CombinedBuildOutputs.insert(output);
}
}
// Write implicit outputs
if (!build.ImplicitOuts.empty()) {
- buildStr += " |";
+ // Assume Ninja is new enough to support implicit outputs.
+ // Callers should not populate this field otherwise.
+ buildStr = cmStrCat(buildStr, " |");
for (std::string const& implicitOut : build.ImplicitOuts) {
- buildStr += cmStrCat(' ', this->EncodePath(implicitOut));
+ buildStr = cmStrCat(buildStr, ' ', this->EncodePath(implicitOut));
+ if (this->ComputingUnknownDependencies) {
+ this->CombinedBuildOutputs.insert(implicitOut);
+ }
+ }
+ }
+
+ // Repeat some outputs, but expressed as absolute paths.
+ // This helps Ninja handle absolute paths found in a depfile.
+ // FIXME: Unfortunately this causes Ninja to stat the file twice.
+ // We could avoid this if Ninja Issue 1251 were fixed.
+ if (!build.WorkDirOuts.empty()) {
+ if (this->SupportsImplicitOuts() && build.ImplicitOuts.empty()) {
+ // Make them implicit outputs if supported by this version of Ninja.
+ buildStr = cmStrCat(buildStr, " |");
+ }
+ for (std::string const& workdirOut : build.WorkDirOuts) {
+ buildStr = cmStrCat(buildStr, " ${cmake_ninja_workdir}",
+ this->EncodePath(workdirOut));
}
}
- buildStr += ':';
// Write the rule.
- buildStr += cmStrCat(' ', build.Rule);
+ buildStr = cmStrCat(buildStr, ": ", build.Rule);
}
std::string arguments;
@@ -305,21 +327,46 @@ void cmGlobalNinjaGenerator::AddCustomCommandRule()
this->AddRule(rule);
}
+void cmGlobalNinjaGenerator::CCOutputs::Add(
+ std::vector<std::string> const& paths)
+{
+ for (std::string const& path : paths) {
+ std::string out = this->GG->ConvertToNinjaPath(path);
+ if (!cmSystemTools::FileIsFullPath(out)) {
+ // This output is expressed as a relative path. Repeat it,
+ // but expressed as an absolute path for Ninja Issue 1251.
+ this->WorkDirOuts.emplace_back(out);
+ this->GG->SeenCustomCommandOutput(this->GG->ConvertToNinjaAbsPath(path));
+ }
+ this->GG->SeenCustomCommandOutput(out);
+ this->ExplicitOuts.emplace_back(std::move(out));
+ }
+}
+
void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
- const std::string& command, const std::string& description,
- const std::string& comment, const std::string& depfile,
- const std::string& job_pool, bool uses_terminal, bool restat,
- const cmNinjaDeps& outputs, const std::string& config,
- const cmNinjaDeps& explicitDeps, const cmNinjaDeps& orderOnlyDeps)
+ std::string const& command, std::string const& description,
+ std::string const& comment, std::string const& depfile,
+ std::string const& job_pool, bool uses_terminal, bool restat,
+ std::string const& config, CCOutputs outputs, cmNinjaDeps explicitDeps,
+ cmNinjaDeps orderOnlyDeps)
{
this->AddCustomCommandRule();
+ if (this->ComputingUnknownDependencies) {
+ // we need to track every dependency that comes in, since we are trying
+ // to find dependencies that are side effects of build commands
+ for (std::string const& dep : explicitDeps) {
+ this->CombinedCustomCommandExplicitDependencies.insert(dep);
+ }
+ }
+
{
cmNinjaBuild build("CUSTOM_COMMAND");
build.Comment = comment;
- build.Outputs = outputs;
- build.ExplicitDeps = explicitDeps;
- build.OrderOnlyDeps = orderOnlyDeps;
+ build.Outputs = std::move(outputs.ExplicitOuts);
+ build.WorkDirOuts = std::move(outputs.WorkDirOuts);
+ build.ExplicitDeps = std::move(explicitDeps);
+ build.OrderOnlyDeps = std::move(orderOnlyDeps);
cmNinjaVars& vars = build.Variables;
{
@@ -349,14 +396,6 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
this->WriteBuild(*this->GetImplFileStream(config), build);
}
}
-
- if (this->ComputingUnknownDependencies) {
- // we need to track every dependency that comes in, since we are trying
- // to find dependencies that are side effects of build commands
- for (std::string const& dep : explicitDeps) {
- this->CombinedCustomCommandExplicitDependencies.insert(dep);
- }
- }
}
void cmGlobalNinjaGenerator::AddMacOSXContentRule()
@@ -503,14 +542,7 @@ std::unique_ptr<cmLocalGenerator> cmGlobalNinjaGenerator::CreateLocalGenerator(
codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const
{
-#ifdef _WIN32
- // Ninja on Windows does not support non-ANSI characters.
- // https://github.com/ninja-build/ninja/issues/1195
- return codecvt::ANSI;
-#else
- // No encoding conversion needed on other platforms.
- return codecvt::None;
-#endif
+ return this->NinjaExpectedEncoding;
}
void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry)
@@ -732,6 +764,61 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures()
this->NinjaSupportsMetadataOnRegeneration = !cmSystemTools::VersionCompare(
cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
RequiredNinjaVersionForMetadataOnRegeneration().c_str());
+#ifdef _WIN32
+ this->NinjaSupportsCodePage = !cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
+ RequiredNinjaVersionForCodePage().c_str());
+ if (this->NinjaSupportsCodePage) {
+ this->CheckNinjaCodePage();
+ } else {
+ this->NinjaExpectedEncoding = codecvt::ANSI;
+ }
+#endif
+}
+
+void cmGlobalNinjaGenerator::CheckNinjaCodePage()
+{
+ std::vector<std::string> command{ this->NinjaCommand, "-t", "wincodepage" };
+ std::string output;
+ std::string error;
+ int result;
+ if (!cmSystemTools::RunSingleCommand(command, &output, &error, &result,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("Running\n '",
+ cmJoin(command, "' '"),
+ "'\n"
+ "failed with:\n ",
+ error));
+ cmSystemTools::SetFatalErrorOccured();
+ } else if (result == 0) {
+ std::istringstream outputStream(output);
+ std::string line;
+ bool found = false;
+ while (cmSystemTools::GetLineFromStream(outputStream, line)) {
+ if (cmHasLiteralPrefix(line, "Build file encoding: ")) {
+ cm::string_view lineView(line);
+ cm::string_view encoding =
+ lineView.substr(cmStrLen("Build file encoding: "));
+ if (encoding == "UTF-8") {
+ // Ninja expects UTF-8. We use that internally. No conversion needed.
+ this->NinjaExpectedEncoding = codecvt::None;
+ } else {
+ this->NinjaExpectedEncoding = codecvt::ANSI;
+ }
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::WARNING,
+ "Could not determine Ninja's code page, defaulting to UTF-8");
+ this->NinjaExpectedEncoding = codecvt::None;
+ }
+ } else {
+ this->NinjaExpectedEncoding = codecvt::ANSI;
+ }
}
bool cmGlobalNinjaGenerator::CheckLanguages(
@@ -1073,10 +1160,8 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
return f->second;
}
- const auto& ng =
- cm::static_reference_cast<cmLocalNinjaGenerator>(this->LocalGenerators[0]);
- std::string const& bin_dir = ng.GetState()->GetBinaryDirectory();
- std::string convPath = ng.MaybeConvertToRelativePath(bin_dir, path);
+ std::string convPath =
+ this->LocalGenerators[0]->MaybeRelativeToTopBinDir(path);
convPath = this->NinjaOutputPath(convPath);
#ifdef _WIN32
std::replace(convPath.begin(), convPath.end(), '/', '\\');
@@ -1085,6 +1170,15 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
.first->second;
}
+std::string cmGlobalNinjaGenerator::ConvertToNinjaAbsPath(
+ std::string path) const
+{
+#ifdef _WIN32
+ std::replace(path.begin(), path.end(), '/', '\\');
+#endif
+ return path;
+}
+
void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName,
const std::string& config)
{
@@ -1150,6 +1244,8 @@ void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os) const
void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
{
for (auto const& asd : this->AssumedSourceDependencies) {
+ CCOutputs outputs(this);
+ outputs.ExplicitOuts.emplace_back(asd.first);
cmNinjaDeps orderOnlyDeps;
std::copy(asd.second.begin(), asd.second.end(),
std::back_inserter(orderOnlyDeps));
@@ -1158,8 +1254,8 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
"Assume dependencies for generated source file.",
/*depfile*/ "", /*job_pool*/ "",
/*uses_terminal*/ false,
- /*restat*/ true, cmNinjaDeps(1, asd.first), "", cmNinjaDeps(),
- orderOnlyDeps);
+ /*restat*/ true, std::string(), outputs, cmNinjaDeps(),
+ std::move(orderOnlyDeps));
}
}
@@ -2198,14 +2294,22 @@ Compilation of source files within a target is split into the following steps:
(because the latter consumes the module).
*/
-static std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
+namespace {
+
+struct cmSourceInfo
+{
+ cmScanDepInfo ScanDep;
+ std::vector<std::string> Includes;
+};
+
+cm::optional<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
std::string const& arg_tdi, std::string const& arg_pp);
+}
int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd)
{
std::string arg_tdi;
- std::string arg_src;
std::string arg_pp;
std::string arg_dep;
std::string arg_obj;
@@ -2214,8 +2318,6 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
for (std::string const& arg : cmMakeRange(argBeg, argEnd)) {
if (cmHasLiteralPrefix(arg, "--tdi=")) {
arg_tdi = arg.substr(6);
- } else if (cmHasLiteralPrefix(arg, "--src=")) {
- arg_src = arg.substr(6);
} else if (cmHasLiteralPrefix(arg, "--pp=")) {
arg_pp = arg.substr(5);
} else if (cmHasLiteralPrefix(arg, "--dep=")) {
@@ -2256,11 +2358,8 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
cmSystemTools::Error("-E cmake_ninja_depends requires value for --lang=");
return 1;
}
- if (arg_src.empty()) {
- arg_src = cmStrCat("<", arg_obj, " input file>");
- }
- std::unique_ptr<cmSourceInfo> info;
+ cm::optional<cmSourceInfo> info;
if (arg_lang == "Fortran") {
info = cmcmd_cmake_ninja_depends_fortran(arg_tdi, arg_pp);
} else {
@@ -2275,7 +2374,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
return 1;
}
- info->PrimaryOutput = arg_obj;
+ info->ScanDep.PrimaryOutput = arg_obj;
{
cmGeneratedFileStream depfile(arg_dep);
@@ -2286,7 +2385,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
depfile << "\n";
}
- if (!cmScanDepFormat_P1689_Write(arg_ddi, arg_src, *info)) {
+ if (!cmScanDepFormat_P1689_Write(arg_ddi, info->ScanDep)) {
cmSystemTools::Error(
cmStrCat("-E cmake_ninja_depends failed to write ", arg_ddi));
return 1;
@@ -2294,11 +2393,16 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
return 0;
}
-std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
+namespace {
+
+cm::optional<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
std::string const& arg_tdi, std::string const& arg_pp)
{
+ cm::optional<cmSourceInfo> info;
cmFortranCompiler fc;
std::vector<std::string> includes;
+ std::string dir_top_bld;
+ std::string module_dir;
{
Json::Value tdio;
Json::Value const& tdi = tdio;
@@ -2309,10 +2413,15 @@ std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
cmSystemTools::Error(
cmStrCat("-E cmake_ninja_depends failed to parse ", arg_tdi,
reader.getFormattedErrorMessages()));
- return nullptr;
+ return info;
}
}
+ dir_top_bld = tdi["dir-top-bld"].asString();
+ if (!dir_top_bld.empty() && !cmHasLiteralSuffix(dir_top_bld, "/")) {
+ dir_top_bld += '/';
+ }
+
Json::Value const& tdi_include_dirs = tdi["include-dirs"];
if (tdi_include_dirs.isArray()) {
for (auto const& tdi_include_dir : tdi_include_dirs) {
@@ -2320,6 +2429,12 @@ std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
}
}
+ Json::Value const& tdi_module_dir = tdi["module-dir"];
+ module_dir = tdi_module_dir.asString();
+ if (!module_dir.empty() && !cmHasLiteralSuffix(module_dir, "/")) {
+ module_dir += '/';
+ }
+
Json::Value const& tdi_compiler_id = tdi["compiler-id"];
fc.Id = tdi_compiler_id.asString();
@@ -2336,19 +2451,25 @@ std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
if (!cmFortranParser_FilePush(&parser, arg_pp.c_str())) {
cmSystemTools::Error(
cmStrCat("-E cmake_ninja_depends failed to open ", arg_pp));
- return nullptr;
+ return info;
}
if (cmFortran_yyparse(parser.Scanner) != 0) {
// Failed to parse the file.
- return nullptr;
+ return info;
}
- auto info = cm::make_unique<cmSourceInfo>();
+ info = cmSourceInfo();
for (std::string const& provide : finfo.Provides) {
cmSourceReqInfo src_info;
src_info.LogicalName = provide;
- src_info.CompiledModulePath = provide;
- info->Provides.emplace_back(src_info);
+ if (!module_dir.empty()) {
+ std::string mod = cmStrCat(module_dir, provide);
+ if (!dir_top_bld.empty() && cmHasPrefix(mod, dir_top_bld)) {
+ mod = mod.substr(dir_top_bld.size());
+ }
+ src_info.CompiledModulePath = std::move(mod);
+ }
+ info->ScanDep.Provides.emplace_back(src_info);
}
for (std::string const& require : finfo.Requires) {
// Require modules not provided in the same source.
@@ -2357,14 +2478,14 @@ std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
}
cmSourceReqInfo src_info;
src_info.LogicalName = require;
- src_info.CompiledModulePath = require;
- info->Requires.emplace_back(src_info);
+ info->ScanDep.Requires.emplace_back(src_info);
}
for (std::string const& include : finfo.Includes) {
info->Includes.push_back(include);
}
return info;
}
+}
bool cmGlobalNinjaGenerator::WriteDyndepFile(
std::string const& dir_top_src, std::string const& dir_top_bld,
@@ -2379,17 +2500,17 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
cmStateSnapshot snapshot = this->GetCMakeInstance()->GetCurrentSnapshot();
snapshot.GetDirectory().SetCurrentSource(dir_cur_src);
snapshot.GetDirectory().SetCurrentBinary(dir_cur_bld);
- snapshot.GetDirectory().SetRelativePathTopSource(dir_top_src.c_str());
- snapshot.GetDirectory().SetRelativePathTopBinary(dir_top_bld.c_str());
auto mfd = cm::make_unique<cmMakefile>(this, snapshot);
auto lgd = this->CreateLocalGenerator(mfd.get());
+ lgd->SetRelativePathTopSource(dir_top_src);
+ lgd->SetRelativePathTopBinary(dir_top_bld);
this->Makefiles.push_back(std::move(mfd));
this->LocalGenerators.push_back(std::move(lgd));
}
- std::vector<cmSourceInfo> objects;
+ std::vector<cmScanDepInfo> objects;
for (std::string const& arg_ddi : arg_ddis) {
- cmSourceInfo info;
+ cmScanDepInfo info;
if (!cmScanDepFormat_P1689_Parse(arg_ddi, &info)) {
cmSystemTools::Error(
cmStrCat("-E cmake_ninja_dyndep failed to parse ddi file ", arg_ddi));
@@ -2425,10 +2546,20 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
// 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;
- for (cmSourceInfo const& object : objects) {
+ for (cmScanDepInfo const& object : objects) {
for (auto const& p : object.Provides) {
- std::string const mod = cmStrCat(
- module_dir, cmSystemTools::GetFilenameName(p.CompiledModulePath));
+ std::string mod;
+ if (!p.CompiledModulePath.empty()) {
+ // The scanner provided the path to the module file.
+ mod = p.CompiledModulePath;
+ if (!cmSystemTools::FileIsFullPath(mod)) {
+ // Treat relative to work directory (top of build tree).
+ mod = cmSystemTools::CollapseFullPath(mod, dir_top_bld);
+ }
+ } else {
+ // Assume the module file path matches the logical module name.
+ mod = cmStrCat(module_dir, p.LogicalName);
+ }
mod_files[p.LogicalName] = mod;
tm[p.LogicalName] = mod;
}
@@ -2440,7 +2571,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
{
cmNinjaBuild build("dyndep");
build.Outputs.emplace_back("");
- for (cmSourceInfo const& object : objects) {
+ for (cmScanDepInfo const& object : objects) {
build.Outputs[0] = this->ConvertToNinjaPath(object.PrimaryOutput);
build.ImplicitOuts.clear();
for (auto const& p : object.Provides) {
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 0c919ef1d..bb4ce2bf2 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -110,13 +110,29 @@ public:
void WriteBuild(std::ostream& os, cmNinjaBuild const& build,
int cmdLineLimit = 0, bool* usedResponseFile = nullptr);
- void WriteCustomCommandBuild(
- const std::string& command, const std::string& description,
- const std::string& comment, const std::string& depfile,
- const std::string& pool, bool uses_terminal, bool restat,
- const cmNinjaDeps& outputs, const std::string& config,
- const cmNinjaDeps& explicitDeps = cmNinjaDeps(),
- const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps());
+ class CCOutputs
+ {
+ cmGlobalNinjaGenerator* GG;
+
+ public:
+ CCOutputs(cmGlobalNinjaGenerator* gg)
+ : GG(gg)
+ {
+ }
+ void Add(std::vector<std::string> const& outputs);
+ cmNinjaDeps ExplicitOuts;
+ cmNinjaDeps WorkDirOuts;
+ };
+
+ void WriteCustomCommandBuild(std::string const& command,
+ std::string const& description,
+ std::string const& comment,
+ std::string const& depfile,
+ std::string const& pool, bool uses_terminal,
+ bool restat, std::string const& config,
+ CCOutputs outputs,
+ cmNinjaDeps explicitDeps = cmNinjaDeps(),
+ cmNinjaDeps orderOnlyDeps = cmNinjaDeps());
void WriteMacOSXContentBuild(std::string input, std::string output,
const std::string& config);
@@ -245,6 +261,7 @@ public:
}
std::string const& ConvertToNinjaPath(const std::string& path) const;
+ std::string ConvertToNinjaAbsPath(std::string path) const;
struct MapToNinjaPathImpl
{
@@ -388,6 +405,7 @@ public:
{
return "1.10.2";
}
+ static std::string RequiredNinjaVersionForCodePage() { return "1.11"; }
bool SupportsConsolePool() const;
bool SupportsImplicitOuts() const;
bool SupportsManifestRestat() const;
@@ -474,6 +492,7 @@ private:
std::string GetEditCacheCommand() const override;
bool FindMakeProgram(cmMakefile* mf) override;
void CheckNinjaFeatures();
+ void CheckNinjaCodePage();
bool CheckLanguages(std::vector<std::string> const& languages,
cmMakefile* mf) const override;
bool CheckFortran(cmMakefile* mf) const;
@@ -568,6 +587,9 @@ private:
bool NinjaSupportsUnconditionalRecompactTool = false;
bool NinjaSupportsMultipleOutputs = false;
bool NinjaSupportsMetadataOnRegeneration = false;
+ bool NinjaSupportsCodePage = false;
+
+ codecvt::Encoding NinjaExpectedEncoding = codecvt::None;
bool DiagnosedCxxModuleSupport = false;
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 97384cd5a..9c3de1eed 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -22,7 +22,6 @@
#include "cmOutputConverter.h"
#include "cmProperty.h"
#include "cmState.h"
-#include "cmStateDirectory.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -147,7 +146,7 @@ void cmGlobalUnixMakefileGenerator3::Generate()
// write each target's progress.make this loop is done twice. Basically the
// Generate pass counts all the actions, the first loop below determines
// how many actions have progress updates for each target and writes to
- // corrrect variable values for everything except the all targets. The
+ // correct variable values for everything except the all targets. The
// second loop actually writes out correct values for the all targets as
// well. This is because the all targets require more information that is
// computed in the first loop.
@@ -318,16 +317,13 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
const auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(
this->LocalGenerators[0]);
- const std::string& currentBinDir = lg.GetCurrentBinaryDirectory();
// Save the list to the cmake file.
cmakefileStream
<< "# The top level Makefile was generated from the following files:\n"
<< "set(CMAKE_MAKEFILE_DEPENDS\n"
<< " \"CMakeCache.txt\"\n";
for (std::string const& f : lfiles) {
- cmakefileStream << " \""
- << lg.MaybeConvertToRelativePath(currentBinDir, f)
- << "\"\n";
+ cmakefileStream << " \"" << lg.MaybeRelativeToCurBinDir(f) << "\"\n";
}
cmakefileStream << " )\n\n";
@@ -339,17 +335,11 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
// Set the corresponding makefile in the cmake file.
cmakefileStream << "# The corresponding makefile is:\n"
<< "set(CMAKE_MAKEFILE_OUTPUTS\n"
- << " \""
- << lg.MaybeConvertToRelativePath(currentBinDir,
- makefileName)
+ << " \"" << lg.MaybeRelativeToCurBinDir(makefileName)
<< "\"\n"
- << " \""
- << lg.MaybeConvertToRelativePath(currentBinDir, check)
- << "\"\n";
+ << " \"" << lg.MaybeRelativeToCurBinDir(check) << "\"\n";
cmakefileStream << " )\n\n";
- const std::string& binDir = lg.GetBinaryDirectory();
-
// CMake must rerun if a byproduct is missing.
cmakefileStream << "# Byproducts of CMake generate step:\n"
<< "set(CMAKE_MAKEFILE_PRODUCTS\n";
@@ -359,14 +349,12 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
for (const auto& localGen : this->LocalGenerators) {
for (std::string const& outfile :
localGen->GetMakefile()->GetOutputFiles()) {
- cmakefileStream << " \""
- << lg.MaybeConvertToRelativePath(binDir, outfile)
+ cmakefileStream << " \"" << lg.MaybeRelativeToTopBinDir(outfile)
<< "\"\n";
}
tmpStr = cmStrCat(localGen->GetCurrentBinaryDirectory(),
"/CMakeFiles/CMakeDirectoryInformation.cmake");
- cmakefileStream << " \""
- << localGen->MaybeConvertToRelativePath(binDir, tmpStr)
+ cmakefileStream << " \"" << localGen->MaybeRelativeToTopBinDir(tmpStr)
<< "\"\n";
}
cmakefileStream << " )\n\n";
@@ -458,9 +446,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);
// Begin the directory-level rules section.
{
- std::string dir =
- cmSystemTools::ConvertToOutputPath(lg->MaybeConvertToRelativePath(
- lg->GetBinaryDirectory(), lg->GetCurrentBinaryDirectory()));
+ std::string dir = cmSystemTools::ConvertToOutputPath(
+ lg->MaybeRelativeToTopBinDir(lg->GetCurrentBinaryDirectory()));
lg->WriteDivider(ruleFileStream);
if (lg->IsRootMakefile()) {
ruleFileStream << "# Directory level rules for the build root directory";
@@ -564,21 +551,6 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
bool fast, int jobs, bool verbose,
std::vector<std::string> const& makeOptions)
{
- std::unique_ptr<cmMakefile> mfu;
- cmMakefile* mf;
- if (!this->Makefiles.empty()) {
- mf = this->Makefiles[0].get();
- } else {
- cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot();
- snapshot.GetDirectory().SetCurrentSource(
- this->CMakeInstance->GetHomeDirectory());
- snapshot.GetDirectory().SetCurrentBinary(
- this->CMakeInstance->GetHomeOutputDirectory());
- snapshot.SetDefaultDefinitions();
- mfu = cm::make_unique<cmMakefile>(this, snapshot);
- mf = mfu.get();
- }
-
GeneratedMakeCommand makeCommand;
// Make it possible to set verbosity also from command line
@@ -609,9 +581,6 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
if (fast) {
tname += "/fast";
}
- tname =
- mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained(
- mf->GetState()->GetBinaryDirectory(), tname);
cmSystemTools::ConvertToOutputSlashes(tname);
makeCommand.Add(std::move(tname));
}
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index b911eef40..fdb71554c 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -231,6 +231,23 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
return false;
}
+ if (!this->CustomFlagTableDir.empty() &&
+ !(cmSystemTools::FileIsFullPath(this->CustomFlagTableDir) &&
+ cmSystemTools::FileIsDirectory(this->CustomFlagTableDir))) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset\n"
+ " customFlagTableDir=" << this->CustomFlagTableDir << "\n"
+ "that is not an absolute path to an existing directory.";
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
if (cmHasLiteralPrefix(this->GetPlatformToolsetString(), "v140")) {
// The GenerateDebugInformation link setting for the v140 toolset
// in VS 2015 was originally an enum with "No" and "Debug" values,
@@ -263,8 +280,8 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
bcDir = this->VCTargetsPath + "/BuildCustomizations";
} else {
bcDir = this->GetPlatformToolsetCudaCustomDirString() +
- "CUDAVisualStudioIntegration\\extras\\"
- "visual_studio_integration\\MSBuildExtensions";
+ this->GetPlatformToolsetCudaVSIntegrationSubdirString() +
+ "extras\\visual_studio_integration\\MSBuildExtensions";
cmSystemTools::ConvertToUnixSlashes(bcDir);
}
cmsys::Glob gl;
@@ -470,11 +487,27 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
if (this->GeneratorToolsetCudaCustomDir.back() != '\\') {
this->GeneratorToolsetCudaCustomDir.push_back('\\');
}
+ /* check for legacy toolkit folder structure */
+ if (cmsys::SystemTools::FileIsDirectory(
+ cmStrCat(this->GeneratorToolsetCudaCustomDir, "nvcc"))) {
+ this->GeneratorToolsetCudaNvccSubdir = "nvcc\\";
+ }
+ if (cmsys::SystemTools::FileIsDirectory(
+ cmStrCat(this->GeneratorToolsetCudaCustomDir,
+ "CUDAVisualStudioIntegration"))) {
+ this->GeneratorToolsetCudaVSIntegrationSubdir =
+ "CUDAVisualStudioIntegration\\";
+ }
} else {
this->GeneratorToolsetCuda = value;
}
return true;
}
+ if (key == "customFlagTableDir") {
+ this->CustomFlagTableDir = value;
+ cmSystemTools::ConvertToUnixSlashes(this->CustomFlagTableDir);
+ return true;
+ }
if (key == "version") {
this->GeneratorToolsetVersion = value;
return true;
@@ -787,6 +820,18 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDirString() const
return this->GeneratorToolsetCudaCustomDir;
}
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaNvccSubdirString() const
+{
+ return this->GeneratorToolsetCudaNvccSubdir;
+}
+
+std::string const& cmGlobalVisualStudio10Generator::
+ GetPlatformToolsetCudaVSIntegrationSubdirString() const
+{
+ return this->GeneratorToolsetCudaVSIntegrationSubdir;
+}
+
cmGlobalVisualStudio10Generator::AuxToolset
cmGlobalVisualStudio10Generator::FindAuxToolset(std::string&,
std::string&) const
@@ -991,6 +1036,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
cmd.push_back(this->GetMSBuildCommand());
cmd.push_back(vcxproj);
cmd.push_back("/p:Configuration=Debug");
+ cmd.push_back(cmStrCat("/p:Platform=", this->GetPlatformName()));
cmd.push_back(std::string("/p:VisualStudioVersion=") +
this->GetIDEVersion());
std::string out;
@@ -1231,6 +1277,8 @@ const char* cmGlobalVisualStudio10Generator::GetToolsVersion() const
return "15.0";
case cmGlobalVisualStudioGenerator::VS16:
return "16.0";
+ case cmGlobalVisualStudioGenerator::VS17:
+ return "17.0";
}
return "";
}
@@ -1315,10 +1363,8 @@ static unsigned int cmLoadFlagTableSpecial(Json::Value entry,
namespace {
-unsigned long long const vsVer16_10_0 = 4503644629696790;
-
-cmIDEFlagTable const* cmLoadFlagTableJson(
- std::string const& flagJsonPath, cm::optional<unsigned long long> vsver)
+cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath,
+ cm::optional<std::string> vsVer)
{
cmIDEFlagTable* ret = nullptr;
auto savedFlagIterator = loadedFlagJsonFiles.find(flagJsonPath);
@@ -1334,17 +1380,22 @@ cmIDEFlagTable const* cmLoadFlagTableJson(
if (reader.parse(stream, flags, false) && flags.isArray()) {
std::vector<cmIDEFlagTable> flagTable;
for (auto const& flag : flags) {
+ Json::Value const& vsminJson = flag["vsmin"];
+ if (vsminJson.isString()) {
+ std::string const& vsmin = vsminJson.asString();
+ if (!vsmin.empty()) {
+ if (!vsVer ||
+ cmSystemTools::VersionCompareGreater(vsmin, *vsVer)) {
+ continue;
+ }
+ }
+ }
cmIDEFlagTable flagEntry;
flagEntry.IDEName = cmLoadFlagTableString(flag, "name");
flagEntry.commandFlag = cmLoadFlagTableString(flag, "switch");
flagEntry.comment = cmLoadFlagTableString(flag, "comment");
flagEntry.value = cmLoadFlagTableString(flag, "value");
flagEntry.special = cmLoadFlagTableSpecial(flag, "flags");
- // FIXME: Port this version check to a Json field.
- if (vsver && *vsver < vsVer16_10_0 &&
- flagEntry.IDEName == "ExternalWarningLevel") {
- continue;
- }
flagTable.push_back(flagEntry);
}
cmIDEFlagTable endFlag{ "", "", "", "", 0 };
@@ -1357,141 +1408,265 @@ cmIDEFlagTable const* cmLoadFlagTableJson(
}
return ret;
}
+}
-std::string cmGetFlagTableName(std::string const& toolsetName,
- std::string const& table)
+cm::optional<std::string> cmGlobalVisualStudio10Generator::FindFlagTable(
+ cm::string_view toolsetName, cm::string_view table) const
{
- return cmSystemTools::GetCMakeRoot() + "/Templates/MSBuild/FlagTables/" +
- toolsetName + "_" + table + ".json";
-}
+ if (!this->CustomFlagTableDir.empty()) {
+ std::string customFlagTableFile =
+ cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_',
+ toolsetName, '_', table, ".json");
+ if (cmSystemTools::FileExists(customFlagTableFile)) {
+ return customFlagTableFile;
+ }
+ customFlagTableFile =
+ cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_',
+ table, ".json");
+ if (cmSystemTools::FileExists(customFlagTableFile)) {
+ return customFlagTableFile;
+ }
+ }
+ std::string fullPath =
+ cmStrCat(cmSystemTools::GetCMakeRoot(), "/Templates/MSBuild/FlagTables/",
+ toolsetName, '_', table, ".json");
+ if (cmSystemTools::FileExists(fullPath)) {
+ return fullPath;
+ }
+ return {};
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable(
- std::string const& optionsName, std::string const& toolsetName,
- std::string const& defaultName, std::string const& table) const
+ std::string const& toolSpecificName, std::string const& defaultName,
+ std::string const& table) const
{
- cmIDEFlagTable const* ret = nullptr;
-
- cm::optional<unsigned long long> vsver = this->GetVSInstanceVersion();
+ cmMakefile* mf = this->GetCurrentMakefile();
std::string filename;
- if (!optionsName.empty()) {
- filename = cmGetFlagTableName(optionsName, table);
- ret = cmLoadFlagTableJson(filename, vsver);
+ if (!toolSpecificName.empty()) {
+ if (cm::optional<std::string> found =
+ this->FindFlagTable(toolSpecificName, table)) {
+ filename = std::move(*found);
+ } else {
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("JSON flag table for ", table,
+ " not found for toolset ", toolSpecificName));
+ return nullptr;
+ }
} else {
- filename = cmGetFlagTableName(toolsetName, table);
- if (cmSystemTools::FileExists(filename)) {
- ret = cmLoadFlagTableJson(filename, vsver);
+ std::string const& genericName =
+ this->CanonicalToolsetName(this->GetPlatformToolsetString());
+ cm::optional<std::string> found = this->FindFlagTable(genericName, table);
+ if (!found) {
+ found = this->FindFlagTable(defaultName, table);
+ }
+ if (found) {
+ filename = std::move(*found);
} else {
- filename = cmGetFlagTableName(defaultName, table);
- ret = cmLoadFlagTableJson(filename, vsver);
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("JSON flag table for ", table,
+ " not found for toolset ", genericName, " ",
+ defaultName));
+ return nullptr;
}
}
- if (!ret) {
- cmMakefile* mf = this->GetCurrentMakefile();
-
- std::ostringstream e;
- /* clang-format off */
- e << "JSON flag table \"" << filename <<
- "\" could not be loaded.\n";
- /* clang-format on */
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
+ if (cmIDEFlagTable const* ret = cmLoadFlagTableJson(filename, vsVer)) {
+ return ret;
}
- return ret;
+
+ mf->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("JSON flag table could not be loaded:\n ", filename));
+ return nullptr;
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetClFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultCLFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "CL");
+ return LoadFlagTable(this->GetClFlagTableName(),
+ this->DefaultCLFlagTableName, "CL");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable()
const
{
- std::string optionsName = this->ToolsetOptions.GetCSharpFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultCSharpFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp");
+ return LoadFlagTable(this->GetCSharpFlagTableName(),
+ this->DefaultCSharpFlagTableName, "CSharp");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetRcFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultRCFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "RC");
+ return LoadFlagTable(this->GetRcFlagTableName(),
+ this->DefaultRCFlagTableName, "RC");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetLibFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultLibFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB");
+ return LoadFlagTable(this->GetLibFlagTableName(),
+ this->DefaultLibFlagTableName, "LIB");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetLinkFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultLinkFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "Link");
+ return LoadFlagTable(this->GetLinkFlagTableName(),
+ this->DefaultLinkFlagTableName, "Link");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const
{
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultCudaFlagTableName);
- return LoadFlagTable("", toolsetName, defaultName, "Cuda");
+ return LoadFlagTable(std::string(), this->DefaultCudaFlagTableName, "Cuda");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable()
const
{
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultCudaHostFlagTableName);
- return LoadFlagTable("", toolsetName, defaultName, "CudaHost");
+ return LoadFlagTable(std::string(), this->DefaultCudaHostFlagTableName,
+ "CudaHost");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetMasmFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultMasmFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM");
+ return LoadFlagTable(this->GetMasmFlagTableName(),
+ this->DefaultMasmFlagTableName, "MASM");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const
{
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultNasmFlagTableName);
- return LoadFlagTable("", toolsetName, defaultName, "NASM");
+ return LoadFlagTable(std::string(), this->DefaultNasmFlagTableName, "NASM");
+}
+
+std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if (toolset == "v142") {
+ return "v142";
+ } else if (toolset == "v141") {
+ return "v141";
+ } else if (useToolset == "v140") {
+ return "v140";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if (useToolset == "v142") {
+ return "v142";
+ } else if (useToolset == "v141") {
+ return "v141";
+ } else if (useToolset == "v140") {
+ return "v140";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if ((useToolset == "v140") || (useToolset == "v141") ||
+ (useToolset == "v142")) {
+ return "v14";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if ((useToolset == "v140") || (useToolset == "v141") ||
+ (useToolset == "v142")) {
+ return "v14";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if (useToolset == "v142") {
+ return "v142";
+ } else if (useToolset == "v141") {
+ return "v141";
+ } else if (useToolset == "v140") {
+ return "v140";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if ((useToolset == "v140") || (useToolset == "v141") ||
+ (useToolset == "v142")) {
+ return "v14";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::CanonicalToolsetName(
+ std::string const& toolset) const
+{
+ std::size_t length = toolset.length();
+
+ if (cmHasLiteralSuffix(toolset, "_xp")) {
+ length -= 3;
+ }
+
+ return toolset.substr(0, length);
}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 5022a0fe5..b7ae1eecf 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -6,9 +6,9 @@
#include <set>
#include <cm/optional>
+#include <cm/string_view>
#include "cmGlobalVisualStudio8Generator.h"
-#include "cmVisualStudio10ToolsetOptions.h"
/** \class cmGlobalVisualStudio10Generator
* \brief Write a Unix makefiles.
@@ -78,6 +78,13 @@ public:
const char* GetPlatformToolsetCudaCustomDir() const;
std::string const& GetPlatformToolsetCudaCustomDirString() const;
+ /** The nvcc subdirectory of a custom cuda install directory */
+ std::string const& GetPlatformToolsetCudaNvccSubdirString() const;
+
+ /** The visual studio integration subdirectory of a custom cuda install
+ * directory */
+ std::string const& GetPlatformToolsetCudaVSIntegrationSubdirString() const;
+
/** Return whether we need to use No/Debug instead of false/true
for GenerateDebugInformation. */
bool GetPlatformToolsetNeedsDebugEnum() const
@@ -121,10 +128,7 @@ public:
std::string Encoding() override;
const char* GetToolsVersion() const;
- virtual cm::optional<unsigned long long> GetVSInstanceVersion() const
- {
- return {};
- }
+ virtual cm::optional<std::string> GetVSInstanceVersion() const { return {}; }
bool GetSupportsUnityBuilds() const { return this->SupportsUnityBuilds; }
@@ -134,6 +138,8 @@ public:
virtual bool IsStdOutEncodingSupported() const { return false; }
+ virtual bool IsUtf8EncodingSupported() const { return false; }
+
static std::string GetInstalledNsightTegraVersion();
/** Return the first two components of CMAKE_SYSTEM_VERSION. */
@@ -183,8 +189,7 @@ protected:
std::string const& GetMSBuildCommand();
- cmIDEFlagTable const* LoadFlagTable(std::string const& optionsName,
- std::string const& toolsetName,
+ cmIDEFlagTable const* LoadFlagTable(std::string const& toolSpecificName,
std::string const& defaultName,
std::string const& table) const;
@@ -194,6 +199,8 @@ protected:
std::string GeneratorToolsetCustomVCTargetsDir;
std::string GeneratorToolsetCuda;
std::string GeneratorToolsetCudaCustomDir;
+ std::string GeneratorToolsetCudaNvccSubdir;
+ std::string GeneratorToolsetCudaVSIntegrationSubdir;
std::string DefaultPlatformToolset;
std::string DefaultPlatformToolsetHostArchitecture;
std::string DefaultAndroidToolset;
@@ -237,7 +244,6 @@ private:
std::string MSBuildCommand;
bool MSBuildCommandInitialized;
- cmVisualStudio10ToolsetOptions ToolsetOptions;
std::set<std::string> AndroidExecutableWarnings;
virtual std::string FindMSBuildCommand();
std::string FindDevEnvCommand() override;
@@ -249,6 +255,19 @@ private:
bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
+ std::string GetClFlagTableName() const;
+ std::string GetCSharpFlagTableName() const;
+ std::string GetRcFlagTableName() const;
+ std::string GetLibFlagTableName() const;
+ std::string GetLinkFlagTableName() const;
+ std::string GetMasmFlagTableName() const;
+ std::string CanonicalToolsetName(std::string const& toolset) const;
+
+ cm::optional<std::string> FindFlagTable(cm::string_view toolsetName,
+ cm::string_view table) const;
+
+ std::string CustomFlagTableDir;
+
std::string CustomVCTargetsPath;
std::string VCTargetsPath;
bool FindVCTargetsPath(cmMakefile* mf);
diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h
index 6e409cfa9..b11905ec1 100644
--- a/Source/cmGlobalVisualStudio11Generator.h
+++ b/Source/cmGlobalVisualStudio11Generator.h
@@ -24,6 +24,13 @@ public:
bool MatchesGeneratorName(const std::string& name) const override;
+ bool SupportsCustomCommandDepfile() const override { return true; }
+
+ cm::optional<cmDepfileFormat> DepfileFormat() const override
+ {
+ return cmDepfileFormat::MSBuildAdditionalInputs;
+ }
+
protected:
cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name,
std::string const& platformInGeneratorName);
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 75cd71443..0c85a044e 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -367,7 +367,6 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
{
VisualStudioFolders.clear();
- std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
for (cmGeneratorTarget const* target : projectTargets) {
if (!target->IsInBuildSystem()) {
continue;
@@ -390,7 +389,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
if (vcprojName) {
cmLocalGenerator* lg = target->GetLocalGenerator();
std::string dir = lg->GetCurrentBinaryDirectory();
- dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir);
+ dir = root->MaybeRelativeToCurBinDir(dir);
if (dir == ".") {
dir.clear(); // msbuild cannot handle ".\" prefix
}
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index c23ee9451..cdecea03a 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -104,6 +104,8 @@ const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const
return "15.0";
case cmGlobalVisualStudioGenerator::VS16:
return "16.0";
+ case cmGlobalVisualStudioGenerator::VS17:
+ return "17.0";
}
return "";
}
@@ -170,6 +172,15 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
fout << "# Visual Studio Version 16\n";
}
break;
+ case cmGlobalVisualStudioGenerator::VS17:
+ // Visual Studio 17 writes .sln format 12.00
+ fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
+ if (this->ExpressEdition) {
+ fout << "# Visual Studio Express 17 for Windows Desktop\n";
+ } else {
+ fout << "# Visual Studio Version 17\n";
+ }
+ break;
}
}
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 3bfcbd04d..151f39f12 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -38,7 +38,8 @@ public:
/* VS13 = 130 was skipped */
VS14 = 140,
VS15 = 150,
- VS16 = 160
+ VS16 = 160,
+ VS17 = 170
};
virtual ~cmGlobalVisualStudioGenerator();
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index 50dc30b32..4fab0b930 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -79,6 +79,8 @@ static unsigned int VSVersionToMajor(
return 15;
case cmGlobalVisualStudioGenerator::VS16:
return 16;
+ case cmGlobalVisualStudioGenerator::VS17:
+ return 17;
}
return 0;
}
@@ -101,6 +103,9 @@ static const char* VSVersionToToolset(
return "v141";
case cmGlobalVisualStudioGenerator::VS16:
return "v142";
+ case cmGlobalVisualStudioGenerator::VS17:
+ // FIXME: VS 2022 Preview 1 uses v142. Will it be v143 later?
+ return "v142";
}
return "";
}
@@ -118,6 +123,7 @@ static const char* VSVersionToAndroidToolset(
return "Clang_3_8";
case cmGlobalVisualStudioGenerator::VS15:
case cmGlobalVisualStudioGenerator::VS16:
+ case cmGlobalVisualStudioGenerator::VS17:
return "Clang_5_0";
}
return "";
@@ -205,7 +211,6 @@ public:
platforms.emplace_back("Win32");
platforms.emplace_back("ARM");
platforms.emplace_back("ARM64");
- platforms.emplace_back("ARM64EC");
return platforms;
}
@@ -219,6 +224,7 @@ cmGlobalVisualStudioVersionedGenerator::NewFactory15()
}
static const char vs16generatorName[] = "Visual Studio 16 2019";
+static const char vs17generatorName[] = "Visual Studio 17 2022";
// Map generator name without year to name with year.
static const char* cmVS16GenName(const std::string& name, std::string& genName)
@@ -235,6 +241,20 @@ static const char* cmVS16GenName(const std::string& name, std::string& genName)
return p;
}
+static const char* cmVS17GenName(const std::string& name, std::string& genName)
+{
+ if (strncmp(name.c_str(), vs17generatorName,
+ sizeof(vs17generatorName) - 6) != 0) {
+ return 0;
+ }
+ const char* p = name.c_str() + sizeof(vs17generatorName) - 6;
+ if (cmHasLiteralPrefix(p, " 2022")) {
+ p += 5;
+ }
+ genName = std::string(vs17generatorName) + p;
+ return p;
+}
+
class cmGlobalVisualStudioVersionedGenerator::Factory16
: public cmGlobalGeneratorFactory
{
@@ -284,6 +304,7 @@ public:
platforms.emplace_back("Win32");
platforms.emplace_back("ARM");
platforms.emplace_back("ARM64");
+ platforms.emplace_back("ARM64EC");
return platforms;
}
@@ -299,6 +320,71 @@ cmGlobalVisualStudioVersionedGenerator::NewFactory16()
return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory16);
}
+class cmGlobalVisualStudioVersionedGenerator::Factory17
+ : public cmGlobalGeneratorFactory
+{
+public:
+ std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
+ const std::string& name, bool /*allowArch*/, cmake* cm) const override
+ {
+ std::string genName;
+ const char* p = cmVS17GenName(name, genName);
+ if (!p) {
+ return std::unique_ptr<cmGlobalGenerator>();
+ }
+ if (!*p) {
+ return std::unique_ptr<cmGlobalGenerator>(
+ new cmGlobalVisualStudioVersionedGenerator(
+ cmGlobalVisualStudioGenerator::VS17, cm, genName, ""));
+ }
+ return std::unique_ptr<cmGlobalGenerator>();
+ }
+
+ void GetDocumentation(cmDocumentationEntry& entry) const override
+ {
+ entry.Name = std::string(vs17generatorName);
+ entry.Brief = "Generates Visual Studio 2022 project files. "
+ "Use -A option to specify architecture.";
+ }
+
+ std::vector<std::string> GetGeneratorNames() const override
+ {
+ std::vector<std::string> names;
+ names.push_back(vs17generatorName);
+ return names;
+ }
+
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ return std::vector<std::string>();
+ }
+
+ 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("ARM");
+ platforms.emplace_back("ARM64");
+ platforms.emplace_back("ARM64EC");
+ return platforms;
+ }
+
+ std::string GetDefaultPlatformName() const override
+ {
+ return VSHostPlatformName();
+ }
+};
+
+std::unique_ptr<cmGlobalGeneratorFactory>
+cmGlobalVisualStudioVersionedGenerator::NewFactory17()
+{
+ return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory17);
+}
+
cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator(
VSVersion version, cmake* cm, const std::string& name,
std::string const& platformInGeneratorName)
@@ -339,6 +425,11 @@ bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName(
return genName == this->GetName();
}
break;
+ case cmGlobalVisualStudioGenerator::VS17:
+ if (cmVS17GenName(name, genName)) {
+ return genName == this->GetName();
+ }
+ break;
}
return false;
}
@@ -391,11 +482,11 @@ bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance(
return vsSetupAPIHelper.GetVSInstanceInfo(dir);
}
-cm::optional<unsigned long long>
+cm::optional<std::string>
cmGlobalVisualStudioVersionedGenerator::GetVSInstanceVersion() const
{
- cm::optional<unsigned long long> result;
- unsigned long long vsInstanceVersion;
+ cm::optional<std::string> result;
+ std::string vsInstanceVersion;
if (vsSetupAPIHelper.GetVSInstanceVersion(vsInstanceVersion)) {
result = vsInstanceVersion;
}
@@ -411,10 +502,25 @@ bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const
if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS16) {
return false;
}
- unsigned long long const vsInstanceVersion16_7_P2 = 4503631666610212;
- cm::optional<unsigned long long> vsInstanceVersion =
- this->GetVSInstanceVersion();
- return (vsInstanceVersion && *vsInstanceVersion > vsInstanceVersion16_7_P2);
+ static std::string const vsVer16_7_P2 = "16.7.30128.36";
+ cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
+ return (vsVer &&
+ cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer16_7_P2));
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::IsUtf8EncodingSupported() const
+{
+ // Supported from Visual Studio 16.10 Preview 2.
+ if (this->Version > cmGlobalVisualStudioGenerator::VSVersion::VS16) {
+ return true;
+ }
+ if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS16) {
+ return false;
+ }
+ static std::string const vsVer16_10_P2 = "16.10.31213.239";
+ cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
+ return (vsVer &&
+ cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer16_10_P2));
}
const char*
@@ -431,6 +537,7 @@ cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision()
return "2.0";
case cmGlobalVisualStudioGenerator::VS15:
case cmGlobalVisualStudioGenerator::VS16:
+ case cmGlobalVisualStudioGenerator::VS17:
return "3.0";
}
return "";
@@ -610,6 +717,12 @@ std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand()
// Ask Visual Studio Installer tool.
std::string vs;
if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS17) {
+ msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe";
+ if (cmSystemTools::FileExists(msbuild)) {
+ return msbuild;
+ }
+ }
msbuild = vs + "/MSBuild/Current/Bin/MSBuild.exe";
if (cmSystemTools::FileExists(msbuild)) {
return msbuild;
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h
index 105e4954b..f07492dff 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.h
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.h
@@ -21,6 +21,7 @@ class cmGlobalVisualStudioVersionedGenerator
public:
static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory15();
static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory16();
+ static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory17();
bool MatchesGeneratorName(const std::string& name) const override;
@@ -28,13 +29,15 @@ public:
bool GetVSInstance(std::string& dir) const;
- cm::optional<unsigned long long> GetVSInstanceVersion() const override;
+ cm::optional<std::string> GetVSInstanceVersion() const override;
AuxToolset FindAuxToolset(std::string& version,
std::string& props) const override;
bool IsStdOutEncodingSupported() const override;
+ bool IsUtf8EncodingSupported() const override;
+
const char* GetAndroidApplicationTypeRevision() const override;
protected:
@@ -66,5 +69,7 @@ private:
friend class Factory15;
class Factory16;
friend class Factory16;
+ class Factory17;
+ friend class Factory17;
mutable cmVSSetupAPIHelper vsSetupAPIHelper;
};
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index d6cc423bf..77403b076 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -17,6 +17,7 @@
#include "cmsys/RegularExpression.hxx"
+#include "cmCMakePath.h"
#include "cmComputeLinkInformation.h"
#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
@@ -392,7 +393,7 @@ bool cmGlobalXCodeGenerator::ProcessGeneratorToolsetField(
" ", this->GetName(), "\n"
"toolset specification field\n"
" buildsystem=", value, "\n"
- "value is unkonwn. It must be '1' or '12'."
+ "value is unknown. It must be '1' or '12'."
);
/* clang-format on */
mf->IssueMessage(MessageType::FATAL_ERROR, e);
@@ -585,13 +586,7 @@ void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root)
{
this->CurrentProject = root->GetProjectName();
this->SetCurrentLocalGenerator(root);
- cmSystemTools::SplitPath(
- this->CurrentLocalGenerator->GetCurrentSourceDirectory(),
- this->ProjectSourceDirectoryComponents);
- cmSystemTools::SplitPath(
- this->CurrentLocalGenerator->GetCurrentBinaryDirectory(),
- this->ProjectOutputDirectoryComponents);
-
+ this->CurrentRootGenerator = root;
this->CurrentXCodeHackMakefile =
cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts");
cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile);
@@ -991,7 +986,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES),
*sf);
}
- lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true));
+ lg->AppendFlags(flags,
+ lg->GetIncludeFlags(includes, gtgt, lang, std::string()));
cmXCodeObject* buildFile =
this->CreateXCodeBuildFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf);
@@ -1863,9 +1859,20 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase(
std::set<std::string> allConfigInputs;
std::set<std::string> allConfigOutputs;
+ cmXCodeObject* buildPhase =
+ this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase,
+ cmStrCat(gt->GetName(), ':', sf->GetFullPath()));
+
+ auto depfilesDirectory = cmStrCat(
+ gt->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/CMakeFiles/d/");
+ auto depfilesPrefix = cmStrCat(depfilesDirectory, buildPhase->GetId(), ".");
+
std::string shellScript = "set -e\n";
for (std::string const& configName : this->CurrentConfigurationTypes) {
- cmCustomCommandGenerator ccg(cc, configName, this->CurrentLocalGenerator);
+ cmCustomCommandGenerator ccg(
+ cc, configName, this->CurrentLocalGenerator, true, {},
+ [&depfilesPrefix](const std::string& config, const std::string&)
+ -> std::string { return cmStrCat(depfilesPrefix, config, ".d"); });
std::vector<std::string> realDepends;
realDepends.reserve(ccg.GetDepends().size());
for (auto const& d : ccg.GetDepends()) {
@@ -1885,9 +1892,22 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase(
"\"; then :\n", this->ConstructScript(ccg), "fi\n");
}
- cmXCodeObject* buildPhase =
- this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase,
- cmStrCat(gt->GetName(), ':', sf->GetFullPath()));
+ if (!cc.GetDepfile().empty()) {
+ buildPhase->AddAttribute(
+ "dependencyFile",
+ this->CreateString(cmStrCat(depfilesDirectory, buildPhase->GetId(),
+ ".$(CONFIGURATION).d")));
+ // to avoid spurious errors during first build, create empty dependency
+ // files
+ cmSystemTools::MakeDirectory(depfilesDirectory);
+ for (std::string const& configName : this->CurrentConfigurationTypes) {
+ auto file = cmStrCat(depfilesPrefix, configName, ".d");
+ if (!cmSystemTools::FileExists(file)) {
+ cmSystemTools::Touch(file, true);
+ }
+ }
+ }
+
buildPhase->AddAttribute("buildActionMask",
this->CreateString("2147483647"));
cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
@@ -2187,9 +2207,33 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
}
}
makefileStream << "\n\n";
+
+ auto depfilesDirectory =
+ cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/d/");
+
for (auto const& command : commands) {
- cmCustomCommandGenerator ccg(command, configName,
- this->CurrentLocalGenerator);
+ cmCustomCommandGenerator ccg(
+ command, configName, this->CurrentLocalGenerator, true, {},
+ [this, &depfilesDirectory](const std::string& config,
+ const std::string& file) -> std::string {
+ return cmStrCat(
+ depfilesDirectory,
+ this->GetObjectId(cmXCodeObject::PBXShellScriptBuildPhase, file),
+ ".", config, ".d");
+ });
+
+ auto depfile = ccg.GetInternalDepfile();
+ if (!depfile.empty()) {
+ makefileStream << "include "
+ << cmSystemTools::ConvertToOutputPath(depfile) << "\n\n";
+
+ cmSystemTools::MakeDirectory(depfilesDirectory);
+ if (!cmSystemTools::FileExists(depfile)) {
+ cmSystemTools::Touch(depfile, true);
+ }
+ }
+
std::vector<std::string> realDepends;
realDepends.reserve(ccg.GetDepends().size());
for (auto const& d : ccg.GetDepends()) {
@@ -2695,7 +2739,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// GNU assembly files (#16449)
for (auto const& language : languages) {
std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags(
- includes, gtgt, language, true, false, configName);
+ includes, gtgt, language, configName);
if (!includeFlags.empty()) {
cflags[language] += " " + includeFlags;
@@ -3410,7 +3454,9 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
libItem.Target->GetType() == cmStateEnums::SHARED_LIBRARY ||
libItem.Target->GetType() == cmStateEnums::MODULE_LIBRARY ||
libItem.Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY)) ||
- (!libItem.Target && libItem.IsPath && forceLinkPhase))) {
+ (!libItem.Target &&
+ libItem.IsPath == cmComputeLinkInformation::ItemIsPath::Yes &&
+ forceLinkPhase))) {
std::string libName;
bool canUseLinkPhase = true;
if (libItem.Target) {
@@ -3521,7 +3567,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
auto* libTarget = FindXCodeTarget(libItem->Target);
cmXCodeObject* buildFile;
if (!libTarget) {
- if (libItem->IsPath) {
+ if (libItem->IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
// Get or create a direct file ref in the root project
auto cleanPath = libItem->Value.Value;
if (cmSystemTools::FileIsFullPath(cleanPath)) {
@@ -3680,7 +3726,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
BuildObjectListOrString libPaths(this, true);
for (auto const& libItem : configItemMap[configName]) {
auto const& libName = *libItem;
- if (libName.IsPath) {
+ if (libName.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
auto cleanPath = libName.Value.Value;
if (cmSystemTools::FileIsFullPath(cleanPath)) {
cleanPath = cmSystemTools::CollapseFullPath(cleanPath);
@@ -3727,7 +3773,10 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
}
-void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
+void cmGlobalXCodeGenerator::AddEmbeddedObjects(
+ cmXCodeObject* target, const std::string& copyFilesBuildPhaseName,
+ const std::string& embedPropertyName, const std::string& dstSubfolderSpec,
+ int actionsOnByDefault)
{
cmGeneratorTarget* gt = target->GetTarget();
if (!gt) {
@@ -3743,7 +3792,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
if (!(isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
return;
}
- cmProp files = gt->GetProperty("XCODE_EMBED_FRAMEWORKS");
+ cmProp files = gt->GetProperty(embedPropertyName);
if (!files) {
return;
}
@@ -3751,16 +3800,15 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
// Create an "Embedded Frameworks" build phase
auto* copyFilesBuildPhase =
this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
- std::string copyFilesBuildPhaseName = "Embed Frameworks";
- std::string destinationFrameworks = "10";
copyFilesBuildPhase->SetComment(copyFilesBuildPhaseName);
copyFilesBuildPhase->AddAttribute("buildActionMask",
this->CreateString("2147483647"));
copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
- this->CreateString(destinationFrameworks));
+ this->CreateString(dstSubfolderSpec));
copyFilesBuildPhase->AddAttribute(
"name", this->CreateString(copyFilesBuildPhaseName));
- if (cmProp fwEmbedPath = gt->GetProperty("XCODE_EMBED_FRAMEWORKS_PATH")) {
+ if (cmProp fwEmbedPath =
+ gt->GetProperty(cmStrCat(embedPropertyName, "_PATH"))) {
copyFilesBuildPhase->AddAttribute("dstPath",
this->CreateString(*fwEmbedPath));
} else {
@@ -3774,10 +3822,10 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
for (std::string const& relFile : relFiles) {
cmXCodeObject* buildFile{ nullptr };
std::string filePath = relFile;
- auto* genTarget = FindGeneratorTarget(relFile);
+ auto* genTarget = this->FindGeneratorTarget(relFile);
if (genTarget) {
// This is a target - get it's product path reference
- auto* xcTarget = FindXCodeTarget(genTarget);
+ auto* xcTarget = this->FindXCodeTarget(genTarget);
if (!xcTarget) {
cmSystemTools::Error("Can not find a target for " +
genTarget->GetName());
@@ -3791,18 +3839,18 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
" is missing product reference");
continue;
}
- auto it = FileRefToEmbedBuildFileMap.find(fileRefObject);
- if (it == FileRefToEmbedBuildFileMap.end()) {
+ auto it = this->FileRefToEmbedBuildFileMap.find(fileRefObject);
+ if (it == this->FileRefToEmbedBuildFileMap.end()) {
buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
buildFile->AddAttribute("fileRef", fileRefObject);
- FileRefToEmbedBuildFileMap[fileRefObject] = buildFile;
+ this->FileRefToEmbedBuildFileMap[fileRefObject] = buildFile;
} else {
buildFile = it->second;
}
} else if (cmSystemTools::IsPathToFramework(relFile)) {
// This is a regular string path - create file reference
- auto it = EmbeddedLibRefs.find(relFile);
- if (it == EmbeddedLibRefs.end()) {
+ auto it = this->EmbeddedLibRefs.find(relFile);
+ if (it == this->EmbeddedLibRefs.end()) {
cmXCodeObject* fileRef =
this->CreateXCodeFileReferenceFromPath(relFile, gt, "", nullptr);
if (fileRef) {
@@ -3828,16 +3876,25 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
cmXCodeObject* settings =
this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- const auto& rmHeadersProp =
- gt->GetSafeProperty("XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY");
- if (cmIsOn(rmHeadersProp)) {
+
+ bool removeHeaders = actionsOnByDefault & RemoveHeadersOnCopyByDefault;
+ if (auto prop = gt->GetProperty(
+ cmStrCat(embedPropertyName, "_REMOVE_HEADERS_ON_COPY"))) {
+ removeHeaders = cmIsOn(*prop);
+ }
+ if (removeHeaders) {
attrs->AddObject(this->CreateString("RemoveHeadersOnCopy"));
}
- const auto& codeSignProp =
- gt->GetSafeProperty("XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY");
- if (cmIsOn(codeSignProp)) {
+
+ bool codeSign = actionsOnByDefault & CodeSignOnCopyByDefault;
+ if (auto prop =
+ gt->GetProperty(cmStrCat(embedPropertyName, "_CODE_SIGN_ON_COPY"))) {
+ codeSign = cmIsOn(*prop);
+ }
+ if (codeSign) {
attrs->AddObject(this->CreateString("CodeSignOnCopy"));
}
+
settings->AddAttributeIfNotEmpty("ATTRIBUTES", attrs);
buildFile->AddAttributeIfNotEmpty("settings", settings);
if (!buildFiles->HasObject(buildFile)) {
@@ -3846,11 +3903,30 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
}
copyFilesBuildPhase->AddAttribute("files", buildFiles);
auto* buildPhases = target->GetAttribute("buildPhases");
- // Insert embed build phase right before the post-build command
+ // Embed-something build phases must be inserted before the post-build
+ // command because that command is expected to be last
buildPhases->InsertObject(buildPhases->GetObjectCount() - 1,
copyFilesBuildPhase);
}
+void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
+{
+ static const auto dstSubfolderSpec = "10";
+
+ this->AddEmbeddedObjects(target, "Embed Frameworks",
+ "XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec,
+ NoActionOnCopyByDefault);
+}
+
+void cmGlobalXCodeGenerator::AddEmbeddedAppExtensions(cmXCodeObject* target)
+{
+ static const auto dstSubfolderSpec = "13";
+
+ this->AddEmbeddedObjects(target, "Embed App Extensions",
+ "XCODE_EMBED_APP_EXTENSIONS", dstSubfolderSpec,
+ RemoveHeadersOnCopyByDefault);
+}
+
bool cmGlobalXCodeGenerator::CreateGroups(
std::vector<cmLocalGenerator*>& generators)
{
@@ -4230,6 +4306,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
for (auto t : targets) {
this->AddDependAndLinkInformation(t);
this->AddEmbeddedFrameworks(t);
+ this->AddEmbeddedAppExtensions(t);
// Inherit project-wide values for any target-specific search paths.
this->InheritBuildSettingAttribute(t, "HEADER_SEARCH_PATHS");
this->InheritBuildSettingAttribute(t, "SYSTEM_HEADER_SEARCH_PATHS");
@@ -4237,6 +4314,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->InheritBuildSettingAttribute(t, "SYSTEM_FRAMEWORK_SEARCH_PATHS");
this->InheritBuildSettingAttribute(t, "LIBRARY_SEARCH_PATHS");
this->InheritBuildSettingAttribute(t, "LD_RUNPATH_SEARCH_PATHS");
+ this->InheritBuildSettingAttribute(t, "GCC_PREPROCESSOR_DEFINITIONS");
+ this->InheritBuildSettingAttribute(t, "OTHER_CFLAGS");
+ this->InheritBuildSettingAttribute(t, "OTHER_LDFLAGS");
}
if (this->XcodeBuildSystem == BuildSystem::One) {
@@ -4537,7 +4617,11 @@ void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings(
switch (this->XcodeBuildSystem) {
case BuildSystem::One:
xout.Element("string", "Original");
- xout.Element("key", "DisableBuildSystemDeprecationWarning");
+ if (this->XcodeVersion >= 130) {
+ xout.Element("key", "DisableBuildSystemDeprecationDiagnostic");
+ } else {
+ xout.Element("key", "DisableBuildSystemDeprecationWarning");
+ }
xout.Element("true");
break;
case BuildSystem::Twelve:
@@ -4620,13 +4704,12 @@ std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p)
// We force conversion because Xcode breakpoints do not work unless
// they are in a file named relative to the source tree.
return cmSystemTools::ForceToRelativePath(
- cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p);
+ this->CurrentRootGenerator->GetCurrentSourceDirectory(), p);
}
std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p)
{
- return this->CurrentLocalGenerator->MaybeConvertToRelativePath(
- cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p);
+ return this->CurrentRootGenerator->MaybeRelativeToCurBinDir(p);
}
std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p)
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 1ab56e20e..1e1b344c9 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -14,6 +14,7 @@
#include <cm/string_view>
#include "cmGlobalGenerator.h"
+#include "cmTransformDepfile.h"
#include "cmXCodeObject.h"
class cmCustomCommand;
@@ -111,6 +112,17 @@ public:
bool ShouldStripResourcePath(cmMakefile*) const override;
+ /**
+ * Used to determine if this generator supports DEPFILE option.
+ */
+ bool SupportsCustomCommandDepfile() const override { return true; }
+ virtual cm::optional<cmDepfileFormat> DepfileFormat() const override
+ {
+ return this->XcodeBuildSystem == BuildSystem::One
+ ? cmDepfileFormat::MakeDepfile
+ : cmDepfileFormat::GccDepfile;
+ }
+
bool SetSystemName(std::string const& s, cmMakefile* mf) override;
bool SetGeneratorToolset(std::string const& ts, bool build,
cmMakefile* mf) override;
@@ -132,6 +144,13 @@ protected:
}
private:
+ enum EmbedActionFlags
+ {
+ NoActionOnCopyByDefault = 0,
+ CodeSignOnCopyByDefault = 1,
+ RemoveHeadersOnCopyByDefault = 2,
+ };
+
bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
bool ProcessGeneratorToolsetField(std::string const& key,
std::string const& value, cmMakefile* mf);
@@ -196,7 +215,13 @@ private:
const char* attribute);
cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt);
void AddDependAndLinkInformation(cmXCodeObject* target);
+ void AddEmbeddedObjects(cmXCodeObject* target,
+ const std::string& copyFilesBuildPhaseName,
+ const std::string& embedPropertyName,
+ const std::string& dstSubfolderSpec,
+ int actionsOnByDefault);
void AddEmbeddedFrameworks(cmXCodeObject* target);
+ void AddEmbeddedAppExtensions(cmXCodeObject* target);
void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target,
cmXCodeObject* buildSettings,
const std::string& configName);
@@ -323,13 +348,12 @@ private:
cmXCodeObject* FrameworkGroup;
cmMakefile* CurrentMakefile;
cmLocalGenerator* CurrentLocalGenerator;
+ cmLocalGenerator* CurrentRootGenerator = nullptr;
std::vector<std::string> CurrentConfigurationTypes;
std::string CurrentReRunCMakeMakefile;
std::string CurrentXCodeHackMakefile;
std::string CurrentProject;
std::set<std::string> TargetDoneSet;
- std::vector<std::string> ProjectSourceDirectoryComponents;
- std::vector<std::string> ProjectOutputDirectoryComponents;
std::map<std::string, cmXCodeObject*> GroupMap;
std::map<std::string, cmXCodeObject*> GroupNameMap;
std::map<std::string, cmXCodeObject*> TargetGroup;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 7788db3bb..79109b508 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -2,7 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallCommand.h"
+#include <algorithm>
+#include <cassert>
#include <cstddef>
+#include <iterator>
#include <set>
#include <sstream>
#include <utility>
@@ -22,6 +25,10 @@
#include "cmInstallExportGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
+#include "cmInstallGetRuntimeDependenciesGenerator.h"
+#include "cmInstallImportedRuntimeArtifactsGenerator.h"
+#include "cmInstallRuntimeDependencySet.h"
+#include "cmInstallRuntimeDependencySetGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmListFileCache.h"
@@ -29,6 +36,7 @@
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmProperty.h"
+#include "cmRuntimeDependencyArchive.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSubcommandTable.h"
@@ -38,6 +46,29 @@
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;
+};
+
+auto const RuntimeDependenciesArgHelper =
+ cmArgumentParser<RuntimeDependenciesArgs>{}
+ .Bind("DIRECTORIES"_s, &RuntimeDependenciesArgs::Directories)
+ .Bind("PRE_INCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreIncludeRegexes)
+ .Bind("PRE_EXCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreExcludeRegexes)
+ .Bind("POST_INCLUDE_REGEXES"_s,
+ &RuntimeDependenciesArgs::PostIncludeRegexes)
+ .Bind("POST_EXCLUDE_REGEXES"_s,
+ &RuntimeDependenciesArgs::PostExcludeRegexes)
+ .Bind("POST_INCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostIncludeFiles)
+ .Bind("POST_EXCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostExcludeFiles);
+
class Helper
{
public:
@@ -145,12 +176,106 @@ std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
args.GetDestination());
}
+void AddInstallRuntimeDependenciesGenerator(
+ Helper& helper, cmInstallRuntimeDependencySet* runtimeDependencySet,
+ const cmInstallCommandArguments& runtimeArgs,
+ const cmInstallCommandArguments& libraryArgs,
+ const cmInstallCommandArguments& frameworkArgs,
+ RuntimeDependenciesArgs runtimeDependenciesArgs, bool& installsRuntime,
+ bool& installsLibrary, bool& installsFramework)
+{
+ bool dllPlatform =
+ !helper.Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
+ bool apple =
+ helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") == "Darwin";
+ auto const& runtimeDependenciesArgsRef =
+ dllPlatform ? runtimeArgs : libraryArgs;
+ std::vector<std::string> configurations =
+ runtimeDependenciesArgsRef.GetConfigurations();
+ if (apple) {
+ std::copy(frameworkArgs.GetConfigurations().begin(),
+ frameworkArgs.GetConfigurations().end(),
+ std::back_inserter(configurations));
+ }
+
+ // Create file(GET_RUNTIME_DEPENDENCIES) generator.
+ auto getRuntimeDependenciesGenerator =
+ cm::make_unique<cmInstallGetRuntimeDependenciesGenerator>(
+ runtimeDependencySet, std::move(runtimeDependenciesArgs.Directories),
+ std::move(runtimeDependenciesArgs.PreIncludeRegexes),
+ std::move(runtimeDependenciesArgs.PreExcludeRegexes),
+ std::move(runtimeDependenciesArgs.PostIncludeRegexes),
+ std::move(runtimeDependenciesArgs.PostExcludeRegexes),
+ std::move(runtimeDependenciesArgs.PostIncludeFiles),
+ std::move(runtimeDependenciesArgs.PostExcludeFiles),
+ runtimeDependenciesArgsRef.GetComponent(),
+ apple ? frameworkArgs.GetComponent() : "", true, "_CMAKE_DEPS",
+ "_CMAKE_RPATH", configurations,
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile),
+ runtimeDependenciesArgsRef.GetExcludeFromAll() &&
+ (apple ? frameworkArgs.GetExcludeFromAll() : true),
+ helper.Makefile->GetBacktrace());
+ helper.Makefile->AddInstallGenerator(
+ std::move(getRuntimeDependenciesGenerator));
+
+ // Create the library dependencies generator.
+ auto libraryRuntimeDependenciesGenerator =
+ cm::make_unique<cmInstallRuntimeDependencySetGenerator>(
+ cmInstallRuntimeDependencySetGenerator::DependencyType::Library,
+ runtimeDependencySet, std::vector<std::string>{}, true, std::string{},
+ true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP",
+ dllPlatform ? helper.GetRuntimeDestination(&runtimeArgs)
+ : helper.GetLibraryDestination(&libraryArgs),
+ runtimeDependenciesArgsRef.GetConfigurations(),
+ runtimeDependenciesArgsRef.GetComponent(),
+ runtimeDependenciesArgsRef.GetPermissions(),
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile),
+ runtimeDependenciesArgsRef.GetExcludeFromAll(),
+ helper.Makefile->GetBacktrace());
+ helper.Makefile->AddInstallGenerator(
+ std::move(libraryRuntimeDependenciesGenerator));
+ if (dllPlatform) {
+ installsRuntime = true;
+ } else {
+ installsLibrary = true;
+ }
+
+ if (apple) {
+ // Create the framework dependencies generator.
+ auto frameworkRuntimeDependenciesGenerator =
+ cm::make_unique<cmInstallRuntimeDependencySetGenerator>(
+ cmInstallRuntimeDependencySetGenerator::DependencyType::Framework,
+ runtimeDependencySet, std::vector<std::string>{}, true, std::string{},
+ true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP",
+ frameworkArgs.GetDestination(), frameworkArgs.GetConfigurations(),
+ frameworkArgs.GetComponent(), frameworkArgs.GetPermissions(),
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile),
+ frameworkArgs.GetExcludeFromAll(), helper.Makefile->GetBacktrace());
+ helper.Makefile->AddInstallGenerator(
+ std::move(frameworkRuntimeDependenciesGenerator));
+ installsFramework = true;
+ }
+}
+
std::set<std::string> const allowedTypes{
"BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF",
"SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO",
"LOCALE", "MAN", "DOC",
};
+template <typename T>
+bool AddBundleExecutable(Helper& helper,
+ cmInstallRuntimeDependencySet* runtimeDependencySet,
+ T&& bundleExecutable)
+{
+ if (!runtimeDependencySet->AddBundleExecutable(bundleExecutable)) {
+ helper.SetError(
+ "A runtime dependency set may only have one bundle executable.");
+ return false;
+ }
+ return true;
+}
+
bool HandleScriptMode(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -161,6 +286,7 @@ bool HandleScriptMode(std::vector<std::string> const& args,
bool doing_script = false;
bool doing_code = false;
bool exclude_from_all = false;
+ bool all_components = false;
// Scan the args once for COMPONENT. Only allow one.
//
@@ -172,6 +298,8 @@ bool HandleScriptMode(std::vector<std::string> const& args,
}
if (args[i] == "EXCLUDE_FROM_ALL") {
exclude_from_all = true;
+ } else if (args[i] == "ALL_COMPONENTS") {
+ all_components = true;
}
}
@@ -182,6 +310,11 @@ bool HandleScriptMode(std::vector<std::string> const& args,
return false;
}
+ if (all_components && componentCount == 1) {
+ status.SetError("ALL_COMPONENTS and COMPONENT are mutually exclusive");
+ return false;
+ }
+
// Scan the args again, this time adding install generators each time we
// encounter a SCRIPT or CODE arg:
//
@@ -208,14 +341,14 @@ bool HandleScriptMode(std::vector<std::string> const& args,
}
helper.Makefile->AddInstallGenerator(
cm::make_unique<cmInstallScriptGenerator>(
- script, false, component, exclude_from_all,
+ script, false, component, exclude_from_all, all_components,
helper.Makefile->GetBacktrace()));
} else if (doing_code) {
doing_code = false;
std::string const& code = arg;
helper.Makefile->AddInstallGenerator(
cm::make_unique<cmInstallScriptGenerator>(
- code, true, component, exclude_from_all,
+ code, true, component, exclude_from_all, all_components,
helper.Makefile->GetBacktrace()));
}
}
@@ -279,13 +412,25 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// These generic args also contain the targets and the export stuff
std::vector<std::string> targetList;
std::string exports;
+ 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.Parse(genericArgVector, &unknownArgs);
+ genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector);
+ genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
+ genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs);
bool success = genericArgs.Finalize();
+ bool withRuntimeDependencies =
+ std::find(parsedArgs.begin(), parsedArgs.end(), "RUNTIME_DEPENDENCIES") !=
+ parsedArgs.end();
+ RuntimeDependenciesArgs runtimeDependenciesArgs =
+ RuntimeDependenciesArgHelper.Parse(runtimeDependenciesArgVector,
+ &unknownArgs);
+
cmInstallCommandArguments archiveArgs(helper.DefaultComponentName);
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
@@ -392,6 +537,49 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
return false;
}
+ cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
+ if (withRuntimeDependencies) {
+ if (!runtimeDependencySetArg.empty()) {
+ status.SetError("TARGETS cannot have both RUNTIME_DEPENDENCIES and "
+ "RUNTIME_DEPENDENCY_SET.");
+ return false;
+ }
+ auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
+ if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
+ system)) {
+ status.SetError(
+ cmStrCat("TARGETS RUNTIME_DEPENDENCIES is not supported on system \"",
+ system, '"'));
+ return false;
+ }
+ if (helper.Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
+ status.SetError("TARGETS RUNTIME_DEPENDENCIES is not supported "
+ "when cross-compiling.");
+ return false;
+ }
+ if (helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") ==
+ "Darwin" &&
+ frameworkArgs.GetDestination().empty()) {
+ status.SetError(
+ "TARGETS RUNTIME_DEPENDENCIES given no FRAMEWORK DESTINATION");
+ return false;
+ }
+ runtimeDependencySet = helper.Makefile->GetGlobalGenerator()
+ ->CreateAnonymousRuntimeDependencySet();
+ } else if (!runtimeDependencySetArg.empty()) {
+ auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
+ if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
+ system)) {
+ status.SetError(cmStrCat(
+ "TARGETS RUNTIME_DEPENDENCY_SET is not supported on system \"", system,
+ '"'));
+ return false;
+ }
+ runtimeDependencySet =
+ helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet(
+ runtimeDependencySetArg);
+ }
+
// Select the mode for installing symlinks to versioned shared libraries.
cmInstallTargetGenerator::NamelinkModeType namelinkMode =
cmInstallTargetGenerator::NamelinkModeNone;
@@ -536,6 +724,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
helper.GetRuntimeDestination(nullptr));
}
+ if (runtimeDependencySet && runtimeGenerator) {
+ runtimeDependencySet->AddLibrary(runtimeGenerator.get());
+ }
} else {
// This is a non-DLL platform.
// If it is marked with FRAMEWORK property use the FRAMEWORK set of
@@ -581,6 +772,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
namelinkOnly =
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
}
+ if (runtimeDependencySet && libraryGenerator) {
+ runtimeDependencySet->AddLibrary(libraryGenerator.get());
+ }
}
} break;
case cmStateEnums::STATIC_LIBRARY: {
@@ -623,6 +817,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
libraryGenerator->SetNamelinkMode(namelinkMode);
namelinkOnly =
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
+ if (runtimeDependencySet) {
+ runtimeDependencySet->AddModule(libraryGenerator.get());
+ }
} else {
status.SetError(
cmStrCat("TARGETS given no LIBRARY DESTINATION for module "
@@ -675,6 +872,12 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
target.GetName(), "\"."));
return false;
}
+ if (runtimeDependencySet) {
+ if (!AddBundleExecutable(helper, runtimeDependencySet,
+ bundleGenerator.get())) {
+ return false;
+ }
+ }
} else {
// Executables use the RUNTIME properties.
if (!runtimeArgs.GetDestination().empty()) {
@@ -683,6 +886,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
runtimeGenerator = CreateInstallTargetGenerator(
target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
helper.GetRuntimeDestination(&runtimeArgs));
+ if (runtimeDependencySet) {
+ runtimeDependencySet->AddExecutable(runtimeGenerator.get());
+ }
}
// On DLL platforms an executable may also have an import
@@ -775,7 +981,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
if (!resourceArgs.GetDestination().empty()) {
resourceGenerator = CreateInstallFilesGenerator(
helper.Makefile, absFiles, resourceArgs, false);
- } else {
+ } else if (!target.IsAppBundleOnApple()) {
cmSystemTools::Message(
cmStrCat("INSTALL TARGETS - target ", target.GetName(),
" has RESOURCE files but no RESOURCE DESTINATION."),
@@ -811,6 +1017,13 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
helper.Makefile->AddInstallGenerator(std::move(resourceGenerator));
}
+ if (withRuntimeDependencies && !runtimeDependencySet->Empty()) {
+ AddInstallRuntimeDependenciesGenerator(
+ helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
+ std::move(runtimeDependenciesArgs), installsRuntime, installsLibrary,
+ installsFramework);
+ }
+
// Tell the global generator about any installation component names
// specified
if (installsArchive) {
@@ -857,6 +1070,266 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
return true;
}
+bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ Helper helper(status);
+
+ // This is the IMPORTED_RUNTIME_ARTIFACTS mode.
+ std::vector<cmTarget*> targets;
+
+ struct ArgVectors
+ {
+ std::vector<std::string> Library;
+ std::vector<std::string> Runtime;
+ std::vector<std::string> Framework;
+ std::vector<std::string> Bundle;
+ };
+
+ static auto const argHelper = cmArgumentParser<ArgVectors>{}
+ .Bind("LIBRARY"_s, &ArgVectors::Library)
+ .Bind("RUNTIME"_s, &ArgVectors::Runtime)
+ .Bind("FRAMEWORK"_s, &ArgVectors::Framework)
+ .Bind("BUNDLE"_s, &ArgVectors::Bundle);
+
+ std::vector<std::string> genericArgVector;
+ ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
+
+ // now parse the generic args (i.e. the ones not specialized on LIBRARY,
+ // RUNTIME etc. (see above)
+ std::vector<std::string> targetList;
+ std::string runtimeDependencySetArg;
+ std::vector<std::string> unknownArgs;
+ cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
+ genericArgs.Bind("IMPORTED_RUNTIME_ARTIFACTS"_s, targetList)
+ .Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
+ genericArgs.Parse(genericArgVector, &unknownArgs);
+ bool success = genericArgs.Finalize();
+
+ cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments bundleArgs(helper.DefaultComponentName);
+
+ // now parse the args for specific parts of the target (e.g. LIBRARY,
+ // RUNTIME etc.
+ libraryArgs.Parse(argVectors.Library, &unknownArgs);
+ runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
+ frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
+ bundleArgs.Parse(argVectors.Bundle, &unknownArgs);
+
+ if (!unknownArgs.empty()) {
+ // Unknown argument.
+ status.SetError(
+ cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given unknown argument \"",
+ unknownArgs[0], "\"."));
+ return false;
+ }
+
+ // apply generic args
+ libraryArgs.SetGenericArguments(&genericArgs);
+ runtimeArgs.SetGenericArguments(&genericArgs);
+ frameworkArgs.SetGenericArguments(&genericArgs);
+ bundleArgs.SetGenericArguments(&genericArgs);
+
+ success = success && libraryArgs.Finalize();
+ success = success && runtimeArgs.Finalize();
+ success = success && frameworkArgs.Finalize();
+ success = success && bundleArgs.Finalize();
+
+ if (!success) {
+ return false;
+ }
+
+ cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
+ if (!runtimeDependencySetArg.empty()) {
+ auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
+ if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
+ system)) {
+ status.SetError(
+ cmStrCat("IMPORTED_RUNTIME_ARTIFACTS RUNTIME_DEPENDENCY_SET is not "
+ "supported on system \"",
+ system, '"'));
+ return false;
+ }
+ runtimeDependencySet =
+ helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet(
+ runtimeDependencySetArg);
+ }
+
+ // Check if there is something to do.
+ if (targetList.empty()) {
+ return true;
+ }
+
+ for (std::string const& tgt : targetList) {
+ if (helper.Makefile->IsAlias(tgt)) {
+ status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"",
+ tgt, "\" which is an alias."));
+ return false;
+ }
+ // Lookup this target in the current directory.
+ cmTarget* target = helper.Makefile->FindTargetToUse(tgt);
+ if (!target || !target->IsImported()) {
+ // If no local target has been found, find it in the global scope.
+ cmTarget* const global_target =
+ helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true);
+ if (global_target && global_target->IsImported()) {
+ target = global_target;
+ }
+ }
+ if (target) {
+ // Found the target. Check its type.
+ if (target->GetType() != cmStateEnums::EXECUTABLE &&
+ target->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ target->GetType() != cmStateEnums::MODULE_LIBRARY) {
+ status.SetError(
+ cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"", tgt,
+ "\" which is not an executable, library, or module."));
+ return false;
+ }
+ // Store the target in the list to be installed.
+ targets.push_back(target);
+ } else {
+ // Did not find the target.
+ status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"",
+ tgt, "\" which does not exist."));
+ return false;
+ }
+ }
+
+ // Keep track of whether we will be performing an installation of
+ // any files of the given type.
+ bool installsLibrary = false;
+ bool installsRuntime = false;
+ bool installsFramework = false;
+ bool installsBundle = false;
+
+ auto const createInstallGenerator =
+ [helper](cmTarget& target, const cmInstallCommandArguments& typeArgs,
+ const std::string& destination)
+ -> std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator> {
+ return cm::make_unique<cmInstallImportedRuntimeArtifactsGenerator>(
+ target.GetName(), destination, typeArgs.GetPermissions(),
+ typeArgs.GetConfigurations(), typeArgs.GetComponent(),
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile),
+ typeArgs.GetExcludeFromAll(), typeArgs.GetOptional(),
+ helper.Makefile->GetBacktrace());
+ };
+
+ // Generate install script code to install the given targets.
+ for (cmTarget* ti : targets) {
+ // Handle each target type.
+ cmTarget& target = *ti;
+ std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
+ libraryGenerator;
+ std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
+ runtimeGenerator;
+ std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
+ frameworkGenerator;
+ std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
+ bundleGenerator;
+
+ switch (target.GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ if (target.IsDLLPlatform()) {
+ runtimeGenerator = createInstallGenerator(
+ target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs));
+ if (runtimeDependencySet) {
+ runtimeDependencySet->AddLibrary(runtimeGenerator.get());
+ }
+ } else if (target.IsFrameworkOnApple()) {
+ if (frameworkArgs.GetDestination().empty()) {
+ status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no "
+ "FRAMEWORK DESTINATION for shared "
+ "library FRAMEWORK target \"",
+ target.GetName(), "\"."));
+ return false;
+ }
+ frameworkGenerator = createInstallGenerator(
+ target, frameworkArgs, frameworkArgs.GetDestination());
+ if (runtimeDependencySet) {
+ runtimeDependencySet->AddLibrary(frameworkGenerator.get());
+ }
+ } else {
+ libraryGenerator = createInstallGenerator(
+ target, libraryArgs, helper.GetLibraryDestination(&libraryArgs));
+ if (runtimeDependencySet) {
+ runtimeDependencySet->AddLibrary(libraryGenerator.get());
+ }
+ }
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ libraryGenerator = createInstallGenerator(
+ target, libraryArgs, helper.GetLibraryDestination(&libraryArgs));
+ if (runtimeDependencySet) {
+ runtimeDependencySet->AddModule(libraryGenerator.get());
+ }
+ break;
+ case cmStateEnums::EXECUTABLE:
+ if (target.IsAppBundleOnApple()) {
+ if (bundleArgs.GetDestination().empty()) {
+ status.SetError(
+ cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no BUNDLE "
+ "DESTINATION for MACOSX_BUNDLE executable target \"",
+ target.GetName(), "\"."));
+ return false;
+ }
+ bundleGenerator = createInstallGenerator(
+ target, bundleArgs, bundleArgs.GetDestination());
+ if (runtimeDependencySet) {
+ if (!AddBundleExecutable(helper, runtimeDependencySet,
+ bundleGenerator.get())) {
+ return false;
+ }
+ }
+ } else {
+ runtimeGenerator = createInstallGenerator(
+ target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs));
+ if (runtimeDependencySet) {
+ runtimeDependencySet->AddExecutable(runtimeGenerator.get());
+ }
+ }
+ break;
+ default:
+ assert(false && "This should never happen");
+ break;
+ }
+
+ // Keep track of whether we're installing anything in each category
+ installsLibrary = installsLibrary || libraryGenerator;
+ installsRuntime = installsRuntime || runtimeGenerator;
+ installsFramework = installsFramework || frameworkGenerator;
+ installsBundle = installsBundle || bundleGenerator;
+
+ helper.Makefile->AddInstallGenerator(std::move(libraryGenerator));
+ helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator));
+ helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator));
+ helper.Makefile->AddInstallGenerator(std::move(bundleGenerator));
+ }
+
+ // Tell the global generator about any installation component names
+ // specified
+ if (installsLibrary) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ libraryArgs.GetComponent());
+ }
+ if (installsRuntime) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ runtimeArgs.GetComponent());
+ }
+ if (installsFramework) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ frameworkArgs.GetComponent());
+ }
+ if (installsBundle) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ bundleArgs.GetComponent());
+ }
+
+ return true;
+}
+
bool HandleFilesMode(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -1469,6 +1942,120 @@ bool HandleExportMode(std::vector<std::string> const& args,
return true;
}
+bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ Helper helper(status);
+
+ auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
+ if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
+ system)) {
+ status.SetError(cmStrCat(
+ "RUNTIME_DEPENDENCY_SET is not supported on system \"", system, '"'));
+ return false;
+ }
+
+ // This is the RUNTIME_DEPENDENCY_SET mode.
+ cmInstallRuntimeDependencySet* runtimeDependencySet;
+
+ struct ArgVectors
+ {
+ std::vector<std::string> Library;
+ std::vector<std::string> Runtime;
+ std::vector<std::string> Framework;
+ };
+
+ static auto const argHelper = cmArgumentParser<ArgVectors>{}
+ .Bind("LIBRARY"_s, &ArgVectors::Library)
+ .Bind("RUNTIME"_s, &ArgVectors::Runtime)
+ .Bind("FRAMEWORK"_s, &ArgVectors::Framework);
+
+ std::vector<std::string> genericArgVector;
+ ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
+
+ // now parse the generic args (i.e. the ones not specialized on LIBRARY,
+ // RUNTIME, FRAMEWORK etc. (see above)
+ // 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);
+ bool success = genericArgs.Finalize();
+
+ cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
+
+ // Now also parse the file(GET_RUNTIME_DEPENDENCY) args
+ std::vector<std::string> unknownArgs;
+ auto runtimeDependencyArgs = RuntimeDependenciesArgHelper.Parse(
+ runtimeDependencyArgVector, &unknownArgs);
+
+ // now parse the args for specific parts of the target (e.g. LIBRARY,
+ // RUNTIME, FRAMEWORK etc.
+ libraryArgs.Parse(argVectors.Library, &unknownArgs);
+ runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
+ frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
+
+ libraryArgs.SetGenericArguments(&genericArgs);
+ runtimeArgs.SetGenericArguments(&genericArgs);
+ frameworkArgs.SetGenericArguments(&genericArgs);
+
+ success = success && libraryArgs.Finalize();
+ success = success && runtimeArgs.Finalize();
+ success = success && frameworkArgs.Finalize();
+
+ if (!success) {
+ return false;
+ }
+
+ if (!unknownArgs.empty()) {
+ helper.SetError(
+ cmStrCat("RUNTIME_DEPENDENCY_SET given unknown argument \"",
+ unknownArgs.front(), "\"."));
+ return false;
+ }
+
+ if (runtimeDependencySetArg.empty()) {
+ helper.SetError(
+ "RUNTIME_DEPENDENCY_SET not given a runtime dependency set.");
+ return false;
+ }
+
+ runtimeDependencySet =
+ helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet(
+ runtimeDependencySetArg);
+
+ bool installsRuntime = false;
+ bool installsLibrary = false;
+ bool installsFramework = false;
+
+ AddInstallRuntimeDependenciesGenerator(
+ helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
+ std::move(runtimeDependencyArgs), installsRuntime, installsLibrary,
+ installsFramework);
+
+ // Tell the global generator about any installation component names
+ // specified
+ if (installsLibrary) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ libraryArgs.GetComponent());
+ }
+ if (installsRuntime) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ runtimeArgs.GetComponent());
+ }
+ if (installsFramework) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ frameworkArgs.GetComponent());
+ }
+
+ return true;
+}
+
bool Helper::MakeFilesFullPath(const char* modeName,
const std::vector<std::string>& relFiles,
std::vector<std::string>& absFiles)
@@ -1482,7 +2069,8 @@ bool Helper::MakeFilesFullPath(const char* modeName,
}
// Make sure the file is not a directory.
- if (gpos == std::string::npos && cmSystemTools::FileIsDirectory(file)) {
+ if (gpos == std::string::npos && !cmSystemTools::FileIsSymlink(file) &&
+ cmSystemTools::FileIsDirectory(file)) {
this->SetError(
cmStrCat(modeName, " given directory \"", relFile, "\" to install."));
return false;
@@ -1696,11 +2284,13 @@ bool cmInstallCommand(std::vector<std::string> const& args,
{ "SCRIPT"_s, HandleScriptMode },
{ "CODE"_s, HandleScriptMode },
{ "TARGETS"_s, HandleTargetsMode },
+ { "IMPORTED_RUNTIME_ARTIFACTS"_s, HandleImportedRuntimeArtifactsMode },
{ "FILES"_s, HandleFilesMode },
{ "PROGRAMS"_s, HandleFilesMode },
{ "DIRECTORY"_s, HandleDirectoryMode },
{ "EXPORT"_s, HandleExportMode },
{ "EXPORT_ANDROID_MK"_s, HandleExportAndroidMKMode },
+ { "RUNTIME_DEPENDENCY_SET"_s, HandleRuntimeDependencySetMode },
};
return subcommand(args[0], args, status);
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index 4eb5f69e4..86362e48b 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -18,7 +18,7 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
MessageLevel message, bool exclude_from_all, std::string literal_args,
bool optional, cmListFileBacktrace backtrace)
: cmInstallGenerator(dest, configurations, component, message,
- exclude_from_all, std::move(backtrace))
+ exclude_from_all, false, std::move(backtrace))
, LocalGenerator(nullptr)
, Directories(dirs)
, FilePermissions(std::move(file_permissions))
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index fdc3f8c1a..d932fd9e6 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -26,7 +26,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
std::string filename, std::string name_space, bool exportOld, bool android,
cmListFileBacktrace backtrace)
: cmInstallGenerator(destination, configurations, component, message,
- exclude_from_all, std::move(backtrace))
+ exclude_from_all, false, std::move(backtrace))
, ExportSet(exportSet)
, FilePermissions(std::move(file_permissions))
, FileName(std::move(filename))
@@ -184,9 +184,8 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
Indent indent)
{
// Remove old per-configuration export files if the main changes.
- std::string installedDir =
- cmStrCat("$ENV{DESTDIR}",
- this->ConvertToAbsoluteDestination(this->Destination), '/');
+ std::string installedDir = cmStrCat(
+ "$ENV{DESTDIR}", ConvertToAbsoluteDestination(this->Destination), '/');
std::string installedFile = cmStrCat(installedDir, this->FileName);
os << indent << "if(EXISTS \"" << installedFile << "\")\n";
Indent indentN = indent.Next();
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index 556c93827..04aaa29a3 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -17,7 +17,7 @@ cmInstallFilesGenerator::cmInstallFilesGenerator(
MessageLevel message, bool exclude_from_all, std::string rename,
bool optional, cmListFileBacktrace backtrace)
: cmInstallGenerator(dest, configurations, component, message,
- exclude_from_all, std::move(backtrace))
+ exclude_from_all, false, std::move(backtrace))
, LocalGenerator(nullptr)
, Files(files)
, FilePermissions(std::move(file_permissions))
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 98e37666d..4cfeb477e 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -2,21 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallGenerator.h"
-#include <ostream>
+#include <sstream>
#include <utility>
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmInstallGenerator::cmInstallGenerator(
std::string destination, std::vector<std::string> const& configurations,
std::string component, MessageLevel message, bool exclude_from_all,
- cmListFileBacktrace backtrace)
+ bool all_components, cmListFileBacktrace backtrace)
: cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations)
, Destination(std::move(destination))
, Component(std::move(component))
, Message(message)
, ExcludeFromAll(exclude_from_all)
+ , AllComponents(all_components)
, Backtrace(std::move(backtrace))
{
}
@@ -41,7 +43,8 @@ void cmInstallGenerator::AddInstallRule(
std::vector<std::string> const& files, bool optional /* = false */,
const char* permissions_file /* = 0 */,
const char* permissions_dir /* = 0 */, const char* rename /* = 0 */,
- const char* literal_args /* = 0 */, Indent indent)
+ const char* literal_args /* = 0 */, Indent indent,
+ const char* files_var /* = 0 */)
{
// Use the FILE command to install the file.
std::string stype;
@@ -68,37 +71,46 @@ void cmInstallGenerator::AddInstallRule(
stype = "FILE";
break;
}
- os << indent;
if (cmSystemTools::FileIsFullPath(dest)) {
- os << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n";
- os << indent << " \"";
- bool firstIteration = true;
- for (std::string const& file : files) {
- if (!firstIteration) {
- os << ";";
+ if (!files.empty()) {
+ os << indent << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n";
+ os << indent << " \"";
+ bool firstIteration = true;
+ for (std::string const& file : files) {
+ if (!firstIteration) {
+ os << ";";
+ }
+ os << dest << "/";
+ if (rename && *rename) {
+ os << rename;
+ } else {
+ os << cmSystemTools::GetFilenameName(file);
+ }
+ firstIteration = false;
}
- os << dest << "/";
- if (rename && *rename) {
- os << rename;
- } else {
- os << cmSystemTools::GetFilenameName(file);
- }
- firstIteration = false;
+ os << "\")\n";
+ }
+ if (files_var) {
+ os << indent << "foreach(_f IN LISTS " << files_var << ")\n";
+ os << indent.Next() << "get_filename_component(_fn \"${_f}\" NAME)\n";
+ os << indent.Next() << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES \""
+ << dest << "/${_fn}\")\n";
+ os << indent << "endforeach()\n";
}
- os << "\")\n";
os << indent << "if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
- os << indent << indent << "message(WARNING \"ABSOLUTE path INSTALL "
+ os << indent.Next() << "message(WARNING \"ABSOLUTE path INSTALL "
<< "DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
os << indent << "endif()\n";
os << indent << "if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
- os << indent << indent << "message(FATAL_ERROR \"ABSOLUTE path INSTALL "
+ os << indent.Next() << "message(FATAL_ERROR \"ABSOLUTE path INSTALL "
<< "DESTINATION forbidden (by caller): "
<< "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
os << indent << "endif()\n";
}
- std::string absDest = this->ConvertToAbsoluteDestination(dest);
- os << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE " << stype;
+ std::string absDest = ConvertToAbsoluteDestination(dest);
+ os << indent << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE "
+ << stype;
if (optional) {
os << " OPTIONAL";
}
@@ -131,6 +143,9 @@ void cmInstallGenerator::AddInstallRule(
for (std::string const& f : files) {
os << "\n" << indent << " \"" << f << "\"";
}
+ if (files_var) {
+ os << " ${" << files_var << "}";
+ }
os << "\n" << indent << " ";
if (!(literal_args && *literal_args)) {
os << " ";
@@ -160,15 +175,20 @@ void cmInstallGenerator::GenerateScript(std::ostream& os)
Indent indent;
// Begin this block of installation.
- std::string component_test =
- this->CreateComponentTest(this->Component, this->ExcludeFromAll);
- os << indent << "if(" << component_test << ")\n";
+ if (!this->AllComponents) {
+ std::string component_test =
+ this->CreateComponentTest(this->Component, this->ExcludeFromAll);
+ os << indent << "if(" << component_test << ")\n";
+ }
// Generate the script possibly with per-configuration code.
- this->GenerateScriptConfigs(os, indent.Next());
+ this->GenerateScriptConfigs(os,
+ this->AllComponents ? indent : indent.Next());
// End this block of installation.
- os << indent << "endif()\n\n";
+ if (!this->AllComponents) {
+ os << indent << "endif()\n\n";
+ }
}
bool cmInstallGenerator::InstallsForConfig(const std::string& config)
@@ -177,7 +197,7 @@ bool cmInstallGenerator::InstallsForConfig(const std::string& config)
}
std::string cmInstallGenerator::ConvertToAbsoluteDestination(
- std::string const& dest) const
+ std::string const& dest)
{
std::string result;
if (!dest.empty() && !cmSystemTools::FileIsFullPath(dest)) {
@@ -205,3 +225,59 @@ cmInstallGenerator::MessageLevel cmInstallGenerator::SelectMessageLevel(
}
return MessageDefault;
}
+
+std::string cmInstallGenerator::GetDestDirPath(std::string const& file)
+{
+ // Construct the path of the file on disk after installation on
+ // which tweaks may be performed.
+ std::string toDestDirPath = "$ENV{DESTDIR}";
+ if (file[0] != '/' && file[0] != '$') {
+ toDestDirPath += "/";
+ }
+ toDestDirPath += file;
+ return toDestDirPath;
+}
+
+void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent,
+ const std::string& config,
+ std::string const& file,
+ const TweakMethod& tweak)
+{
+ std::ostringstream tw;
+ tweak(tw, indent.Next(), config, file);
+ std::string tws = tw.str();
+ if (!tws.empty()) {
+ os << indent << "if(EXISTS \"" << file << "\" AND\n"
+ << indent << " NOT IS_SYMLINK \"" << file << "\")\n";
+ os << tws;
+ os << indent << "endif()\n";
+ }
+}
+
+void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent,
+ const std::string& config,
+ std::string const& dir,
+ std::vector<std::string> const& files,
+ const TweakMethod& tweak)
+{
+ if (files.size() == 1) {
+ // Tweak a single file.
+ AddTweak(os, indent, config, GetDestDirPath(cmStrCat(dir, files[0])),
+ tweak);
+ } else {
+ // Generate a foreach loop to tweak multiple files.
+ std::ostringstream tw;
+ AddTweak(tw, indent.Next(), config, "${file}", tweak);
+ std::string tws = tw.str();
+ if (!tws.empty()) {
+ Indent indent2 = indent.Next().Next();
+ os << indent << "foreach(file\n";
+ for (std::string const& f : files) {
+ os << indent2 << "\"" << GetDestDirPath(cmStrCat(dir, f)) << "\"\n";
+ }
+ os << indent2 << ")\n";
+ os << tws;
+ os << indent << "endforeach()\n";
+ }
+ }
+}
diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index 6cd9ff9bb..d342c9926 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <functional>
#include <iosfwd>
#include <string>
#include <vector>
@@ -33,7 +34,8 @@ public:
cmInstallGenerator(std::string destination,
std::vector<std::string> const& configurations,
std::string component, MessageLevel message,
- bool exclude_from_all, cmListFileBacktrace backtrace);
+ bool exclude_from_all, bool all_components,
+ cmListFileBacktrace backtrace);
~cmInstallGenerator() override;
cmInstallGenerator(cmInstallGenerator const&) = delete;
@@ -48,11 +50,12 @@ public:
std::vector<std::string> const& files, bool optional = false,
const char* permissions_file = nullptr,
const char* permissions_dir = nullptr, const char* rename = nullptr,
- const char* literal_args = nullptr, Indent indent = Indent());
+ const char* literal_args = nullptr, Indent indent = Indent(),
+ const char* files_var = nullptr);
/** Get the install destination as it should appear in the
installation script. */
- std::string ConvertToAbsoluteDestination(std::string const& dest) const;
+ static std::string ConvertToAbsoluteDestination(std::string const& dest);
/** Test if this generator installs something for a given configuration. */
bool InstallsForConfig(const std::string& config);
@@ -65,19 +68,34 @@ public:
std::string const& GetComponent() const { return this->Component; }
bool GetExcludeFromAll() const { return this->ExcludeFromAll; }
+ bool GetAllComponentsFlag() const { return this->AllComponents; }
cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+ static std::string GetDestDirPath(std::string const& file);
+
protected:
void GenerateScript(std::ostream& os) override;
std::string CreateComponentTest(const std::string& component,
bool exclude_from_all);
+ using TweakMethod =
+ std::function<void(std::ostream& os, Indent indent,
+ const std::string& config, const std::string& file)>;
+ static void AddTweak(std::ostream& os, Indent indent,
+ const std::string& config, std::string const& file,
+ const TweakMethod& tweak);
+ static void AddTweak(std::ostream& os, Indent indent,
+ const std::string& config, std::string const& dir,
+ std::vector<std::string> const& files,
+ const TweakMethod& tweak);
+
// Information shared by most generator types.
std::string const Destination;
std::string const Component;
MessageLevel const Message;
bool const ExcludeFromAll;
+ bool const AllComponents;
cmListFileBacktrace const Backtrace;
};
diff --git a/Source/cmInstallGetRuntimeDependenciesGenerator.cxx b/Source/cmInstallGetRuntimeDependenciesGenerator.cxx
new file mode 100644
index 000000000..4d585cec5
--- /dev/null
+++ b/Source/cmInstallGetRuntimeDependenciesGenerator.cxx
@@ -0,0 +1,206 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallGetRuntimeDependenciesGenerator.h"
+
+#include <memory>
+#include <ostream>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/string_view>
+
+#include "cmGeneratorExpression.h"
+#include "cmInstallRuntimeDependencySet.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmStringAlgorithms.h"
+
+namespace {
+template <typename T, typename F>
+void WriteMultiArgument(std::ostream& os, const cm::string_view& keyword,
+ const std::vector<T>& list,
+ cmScriptGeneratorIndent indent, F transform)
+{
+ bool first = true;
+ for (auto const& item : list) {
+ cm::optional<std::string> result = transform(item);
+ if (result) {
+ if (first) {
+ os << indent << " " << keyword << "\n";
+ first = false;
+ }
+ os << indent << " " << *result << "\n";
+ }
+ }
+}
+
+void WriteFilesArgument(
+ std::ostream& os, const cm::string_view& keyword,
+ const std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>>&
+ items,
+ const std::string& config, cmScriptGeneratorIndent indent)
+{
+ WriteMultiArgument(
+ os, keyword, items, indent,
+ [config](const std::unique_ptr<cmInstallRuntimeDependencySet::Item>& i)
+ -> std::string { return cmStrCat('"', i->GetItemPath(config), '"'); });
+}
+
+void WriteGenexEvaluatorArgument(std::ostream& os,
+ const cm::string_view& keyword,
+ const std::vector<std::string>& genexes,
+ const std::string& config,
+ cmLocalGenerator* lg,
+ cmScriptGeneratorIndent indent)
+{
+ WriteMultiArgument(
+ os, keyword, genexes, indent,
+ [config, lg](const std::string& genex) -> cm::optional<std::string> {
+ std::string result = cmGeneratorExpression::Evaluate(genex, lg, config);
+ if (result.empty()) {
+ return cm::nullopt;
+ }
+ return cmOutputConverter::EscapeForCMake(result);
+ });
+}
+}
+
+cmInstallGetRuntimeDependenciesGenerator::
+ cmInstallGetRuntimeDependenciesGenerator(
+ cmInstallRuntimeDependencySet* runtimeDependencySet,
+ 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, std::string libraryComponent,
+ std::string frameworkComponent, bool noInstallRPath, const char* depsVar,
+ const char* rpathPrefix, std::vector<std::string> const& configurations,
+ MessageLevel message, bool exclude_from_all, cmListFileBacktrace backtrace)
+ : cmInstallGenerator("", configurations, "", message, exclude_from_all,
+ false, std::move(backtrace))
+ , RuntimeDependencySet(runtimeDependencySet)
+ , Directories(std::move(directories))
+ , PreIncludeRegexes(std::move(preIncludeRegexes))
+ , PreExcludeRegexes(std::move(preExcludeRegexes))
+ , PostIncludeRegexes(std::move(postIncludeRegexes))
+ , PostExcludeRegexes(std::move(postExcludeRegexes))
+ , PostIncludeFiles(std::move(postIncludeFiles))
+ , PostExcludeFiles(std::move(postExcludeFiles))
+ , LibraryComponent(std::move(libraryComponent))
+ , FrameworkComponent(std::move(frameworkComponent))
+ , NoInstallRPath(noInstallRPath)
+ , DepsVar(depsVar)
+ , RPathPrefix(rpathPrefix)
+{
+ this->ActionsPerConfig = true;
+}
+
+bool cmInstallGetRuntimeDependenciesGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+ return true;
+}
+
+void cmInstallGetRuntimeDependenciesGenerator::GenerateScript(std::ostream& os)
+{
+ // Track indentation.
+ Indent indent;
+
+ // Begin this block of installation.
+ os << indent << "if(";
+ if (this->FrameworkComponent.empty() ||
+ this->FrameworkComponent == this->LibraryComponent) {
+ os << this->CreateComponentTest(this->LibraryComponent,
+ this->ExcludeFromAll);
+ } else {
+ os << this->CreateComponentTest(this->LibraryComponent, true) << " OR "
+ << this->CreateComponentTest(this->FrameworkComponent,
+ this->ExcludeFromAll);
+ }
+ os << ")\n";
+
+ // Generate the script possibly with per-configuration code.
+ this->GenerateScriptConfigs(os, indent.Next());
+
+ // End this block of installation.
+ os << indent << "endif()\n\n";
+}
+
+void cmInstallGetRuntimeDependenciesGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ std::string installNameTool =
+ this->LocalGenerator->GetMakefile()->GetSafeDefinition(
+ "CMAKE_INSTALL_NAME_TOOL");
+
+ os << indent << "file(GET_RUNTIME_DEPENDENCIES\n"
+ << indent << " RESOLVED_DEPENDENCIES_VAR " << this->DepsVar << '\n';
+ WriteFilesArgument(os, "EXECUTABLES"_s,
+ this->RuntimeDependencySet->GetExecutables(), config,
+ indent);
+ WriteFilesArgument(os, "LIBRARIES"_s,
+ this->RuntimeDependencySet->GetLibraries(), config,
+ indent);
+ WriteFilesArgument(os, "MODULES"_s, this->RuntimeDependencySet->GetModules(),
+ config, indent);
+ if (this->RuntimeDependencySet->GetBundleExecutable()) {
+ os << indent << " BUNDLE_EXECUTABLE \""
+ << this->RuntimeDependencySet->GetBundleExecutable()->GetItemPath(
+ config)
+ << "\"\n";
+ }
+ WriteGenexEvaluatorArgument(os, "DIRECTORIES"_s, this->Directories, config,
+ this->LocalGenerator, indent);
+ WriteGenexEvaluatorArgument(os, "PRE_INCLUDE_REGEXES"_s,
+ this->PreIncludeRegexes, config,
+ this->LocalGenerator, indent);
+ WriteGenexEvaluatorArgument(os, "PRE_EXCLUDE_REGEXES"_s,
+ this->PreExcludeRegexes, config,
+ this->LocalGenerator, indent);
+ WriteGenexEvaluatorArgument(os, "POST_INCLUDE_REGEXES"_s,
+ this->PostIncludeRegexes, config,
+ this->LocalGenerator, indent);
+ WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_REGEXES"_s,
+ this->PostExcludeRegexes, config,
+ this->LocalGenerator, indent);
+ WriteGenexEvaluatorArgument(os, "POST_INCLUDE_FILES"_s,
+ this->PostIncludeFiles, config,
+ this->LocalGenerator, indent);
+ WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_FILES"_s,
+ this->PostExcludeFiles, config,
+ this->LocalGenerator, indent);
+
+ std::set<std::string> postExcludeFiles;
+ auto const addPostExclude =
+ [config, &postExcludeFiles, this](
+ const std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>>&
+ tgts) {
+ for (auto const& item : tgts) {
+ item->AddPostExcludeFiles(config, postExcludeFiles,
+ this->RuntimeDependencySet);
+ }
+ };
+ addPostExclude(this->RuntimeDependencySet->GetExecutables());
+ addPostExclude(this->RuntimeDependencySet->GetLibraries());
+ addPostExclude(this->RuntimeDependencySet->GetModules());
+ bool first = true;
+ for (auto const& file : postExcludeFiles) {
+ if (first) {
+ os << indent << " POST_EXCLUDE_FILES_STRICT\n";
+ first = false;
+ }
+ os << indent << " \"" << file << "\"\n";
+ }
+
+ if (!installNameTool.empty() && !this->NoInstallRPath) {
+ os << indent << " RPATH_PREFIX " << this->RPathPrefix << '\n';
+ }
+ os << indent << " )\n";
+}
diff --git a/Source/cmInstallGetRuntimeDependenciesGenerator.h b/Source/cmInstallGetRuntimeDependenciesGenerator.h
new file mode 100644
index 000000000..19f6cc6db
--- /dev/null
+++ b/Source/cmInstallGetRuntimeDependenciesGenerator.h
@@ -0,0 +1,56 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
+#include "cmScriptGenerator.h"
+
+class cmLocalGenerator;
+class cmInstallRuntimeDependencySet;
+
+class cmInstallGetRuntimeDependenciesGenerator : public cmInstallGenerator
+{
+public:
+ cmInstallGetRuntimeDependenciesGenerator(
+ cmInstallRuntimeDependencySet* runtimeDependencySet,
+ 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, std::string libraryComponent,
+ std::string frameworkComponent, bool noInstallRPath, const char* depsVar,
+ const char* rpathPrefix, std::vector<std::string> const& configurations,
+ MessageLevel message, bool exclude_from_all,
+ cmListFileBacktrace backtrace);
+
+ bool Compute(cmLocalGenerator* lg) override;
+
+protected:
+ void GenerateScript(std::ostream& os) override;
+
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) override;
+
+private:
+ cmInstallRuntimeDependencySet* RuntimeDependencySet;
+ 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;
+ std::string LibraryComponent;
+ std::string FrameworkComponent;
+ bool NoInstallRPath;
+ const char* DepsVar;
+ const char* RPathPrefix;
+ cmLocalGenerator* LocalGenerator = nullptr;
+};
diff --git a/Source/cmInstallImportedRuntimeArtifactsGenerator.cxx b/Source/cmInstallImportedRuntimeArtifactsGenerator.cxx
new file mode 100644
index 000000000..01980ac1a
--- /dev/null
+++ b/Source/cmInstallImportedRuntimeArtifactsGenerator.cxx
@@ -0,0 +1,146 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallImportedRuntimeArtifactsGenerator.h"
+
+#include <cassert>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallType.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+
+namespace {
+const cmsys::RegularExpression FrameworkRegularExpression(
+ "^(.*/)?([^/]*)\\.framework/(.*)$");
+
+const cmsys::RegularExpression BundleRegularExpression(
+ "^(.*/)?([^/]*)\\.app/(.*)$");
+
+const cmsys::RegularExpression CFBundleRegularExpression(
+ "^(.*/)?([^/]*)\\.bundle/(.*)$");
+}
+
+cmInstallImportedRuntimeArtifactsGenerator::
+ cmInstallImportedRuntimeArtifactsGenerator(
+ std::string targetName, 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(targetName))
+ , FilePermissions(std::move(file_permissions))
+ , Optional(optional)
+{
+ this->ActionsPerConfig = true;
+}
+
+bool cmInstallImportedRuntimeArtifactsGenerator::Compute(cmLocalGenerator* lg)
+{
+ // Lookup this target in the current directory.
+ this->Target = lg->FindGeneratorTargetToUse(this->TargetName);
+ if (!this->Target || !this->Target->IsImported()) {
+ // If no local target has been found, find it in the global scope.
+ this->Target =
+ lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
+ }
+
+ return true;
+}
+
+std::string cmInstallImportedRuntimeArtifactsGenerator::GetDestination(
+ std::string const& config) const
+{
+ return cmGeneratorExpression::Evaluate(
+ this->Destination, this->Target->GetLocalGenerator(), config);
+}
+
+void cmInstallImportedRuntimeArtifactsGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ auto location = this->Target->GetFullPath(config);
+
+ switch (this->Target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ if (this->Target->IsBundleOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (BundleRegularExpression.find(location.c_str(), match)) {
+ auto bundleDir = match.match(1);
+ auto bundleName = match.match(2);
+ auto bundlePath = cmStrCat(bundleDir, bundleName, ".app");
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_DIRECTORY, { bundlePath },
+ this->Optional, nullptr,
+ this->FilePermissions.c_str(), nullptr,
+ " USE_SOURCE_PERMISSIONS", indent);
+ }
+ } else {
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_EXECUTABLE, { location },
+ this->Optional, this->FilePermissions.c_str(),
+ nullptr, nullptr, nullptr, indent);
+ }
+ break;
+ case cmStateEnums::SHARED_LIBRARY:
+ if (this->Target->IsFrameworkOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (FrameworkRegularExpression.find(location.c_str(), match)) {
+ auto frameworkDir = match.match(1);
+ auto frameworkName = match.match(2);
+ auto frameworkPath =
+ cmStrCat(frameworkDir, frameworkName, ".framework");
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_DIRECTORY, { frameworkPath },
+ this->Optional, nullptr,
+ this->FilePermissions.c_str(), nullptr,
+ " USE_SOURCE_PERMISSIONS", indent);
+ }
+ } else {
+ std::vector<std::string> files{ location };
+ auto soName = this->Target->GetSOName(config);
+ auto soNameFile =
+ cmStrCat(this->Target->GetDirectory(config), '/', soName);
+ if (!soName.empty() && soNameFile != location) {
+ files.push_back(soNameFile);
+ }
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_SHARED_LIBRARY, files,
+ this->Optional, this->FilePermissions.c_str(),
+ nullptr, nullptr, nullptr, indent);
+ }
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ if (this->Target->IsCFBundleOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (CFBundleRegularExpression.find(location.c_str(), match)) {
+ auto bundleDir = match.match(1);
+ auto bundleName = match.match(2);
+ auto bundlePath = cmStrCat(bundleDir, bundleName, ".bundle");
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_DIRECTORY, { bundlePath },
+ this->Optional, nullptr,
+ this->FilePermissions.c_str(), nullptr,
+ " USE_SOURCE_PERMISSIONS", indent);
+ }
+ } else {
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_MODULE_LIBRARY, { location },
+ this->Optional, this->FilePermissions.c_str(),
+ nullptr, nullptr, nullptr, indent);
+ }
+ break;
+ default:
+ assert(false && "This should never happen");
+ break;
+ }
+}
diff --git a/Source/cmInstallImportedRuntimeArtifactsGenerator.h b/Source/cmInstallImportedRuntimeArtifactsGenerator.h
new file mode 100644
index 000000000..9e045ee72
--- /dev/null
+++ b/Source/cmInstallImportedRuntimeArtifactsGenerator.h
@@ -0,0 +1,44 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
+#include "cmScriptGenerator.h"
+
+class cmGeneratorTarget;
+class cmLocalGenerator;
+
+class cmInstallImportedRuntimeArtifactsGenerator : public cmInstallGenerator
+{
+public:
+ cmInstallImportedRuntimeArtifactsGenerator(
+ std::string targetName, 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 = cmListFileBacktrace());
+ ~cmInstallImportedRuntimeArtifactsGenerator() override = default;
+
+ bool Compute(cmLocalGenerator* lg) override;
+
+ cmGeneratorTarget* GetTarget() const { return this->Target; }
+
+ bool GetOptional() const { return this->Optional; }
+
+ std::string GetDestination(std::string const& config) const;
+
+protected:
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) override;
+
+private:
+ std::string const TargetName;
+ cmGeneratorTarget* Target;
+ std::string const FilePermissions;
+ bool const Optional;
+};
diff --git a/Source/cmInstallRuntimeDependencySet.cxx b/Source/cmInstallRuntimeDependencySet.cxx
new file mode 100644
index 000000000..0cef49a2a
--- /dev/null
+++ b/Source/cmInstallRuntimeDependencySet.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 "cmInstallRuntimeDependencySet.h"
+
+#include <set>
+#include <string>
+#include <utility>
+
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallImportedRuntimeArtifactsGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmStateTypes.h"
+#include "cmTargetDepend.h"
+
+cmInstallRuntimeDependencySet::cmInstallRuntimeDependencySet(std::string name)
+ : Name(std::move(name))
+{
+}
+
+void cmInstallRuntimeDependencySet::AddExecutable(
+ std::unique_ptr<Item> executable)
+{
+ this->Executables.push_back(std::move(executable));
+}
+
+void cmInstallRuntimeDependencySet::AddLibrary(std::unique_ptr<Item> library)
+{
+ this->Libraries.push_back(std::move(library));
+}
+
+void cmInstallRuntimeDependencySet::AddModule(std::unique_ptr<Item> module)
+{
+ this->Modules.push_back(std::move(module));
+}
+
+bool cmInstallRuntimeDependencySet::AddBundleExecutable(
+ std::unique_ptr<Item> bundleExecutable)
+{
+ if (this->BundleExecutable) {
+ return false;
+ }
+ this->BundleExecutable = bundleExecutable.get();
+ this->AddExecutable(std::move(bundleExecutable));
+ return true;
+}
+
+std::string cmInstallRuntimeDependencySet::TargetItem::GetItemPath(
+ const std::string& config) const
+{
+ return this->Target->GetTarget()->GetFullPath(config);
+}
+
+namespace {
+const std::set<const cmGeneratorTarget*>& GetTargetDependsClosure(
+ std::map<const cmGeneratorTarget*, std::set<const cmGeneratorTarget*>>&
+ targetDepends,
+ const cmGeneratorTarget* tgt)
+{
+ auto it = targetDepends.insert({ tgt, {} });
+ auto& retval = it.first->second;
+ if (it.second) {
+ auto const& deps = tgt->GetGlobalGenerator()->GetTargetDirectDepends(tgt);
+ for (auto const& dep : deps) {
+ if (!dep.IsCross() && dep.IsLink()) {
+ auto type = dep->GetType();
+ if (type == cmStateEnums::EXECUTABLE ||
+ type == cmStateEnums::SHARED_LIBRARY ||
+ type == cmStateEnums::MODULE_LIBRARY) {
+ retval.insert(dep);
+ }
+ auto const& depDeps = GetTargetDependsClosure(targetDepends, dep);
+ retval.insert(depDeps.begin(), depDeps.end());
+ }
+ }
+ }
+ return retval;
+}
+}
+
+void cmInstallRuntimeDependencySet::TargetItem::AddPostExcludeFiles(
+ const std::string& config, std::set<std::string>& files,
+ cmInstallRuntimeDependencySet* set) const
+{
+ for (auto const* dep : GetTargetDependsClosure(set->TargetDepends,
+ this->Target->GetTarget())) {
+ files.insert(dep->GetFullPath(config));
+ }
+}
+
+std::string cmInstallRuntimeDependencySet::ImportedTargetItem::GetItemPath(
+ const std::string& config) const
+{
+ return this->Target->GetTarget()->GetFullPath(config);
+}
diff --git a/Source/cmInstallRuntimeDependencySet.h b/Source/cmInstallRuntimeDependencySet.h
new file mode 100644
index 000000000..7f5162458
--- /dev/null
+++ b/Source/cmInstallRuntimeDependencySet.h
@@ -0,0 +1,163 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <cm/memory>
+#include <cm/string_view>
+#include <cmext/string_view>
+
+class cmGeneratorTarget;
+class cmInstallImportedRuntimeArtifactsGenerator;
+class cmInstallTargetGenerator;
+
+class cmInstallRuntimeDependencySet
+{
+public:
+ cmInstallRuntimeDependencySet(std::string name = "");
+
+ cmInstallRuntimeDependencySet(const cmInstallRuntimeDependencySet&) = delete;
+ cmInstallRuntimeDependencySet& operator=(
+ const cmInstallRuntimeDependencySet&) = delete;
+
+ cm::string_view GetName() const { return this->Name; }
+
+ cm::string_view GetDisplayName() const
+ {
+ if (this->Name.empty()) {
+ return "<anonymous>"_s;
+ }
+ return this->Name;
+ }
+
+ class Item
+ {
+ public:
+ virtual ~Item() = default;
+
+ virtual std::string GetItemPath(const std::string& config) const = 0;
+
+ virtual void AddPostExcludeFiles(
+ const std::string& /*config*/, std::set<std::string>& /*files*/,
+ cmInstallRuntimeDependencySet* /*set*/) const
+ {
+ }
+ };
+
+ class TargetItem : public Item
+ {
+ public:
+ TargetItem(cmInstallTargetGenerator* target)
+ : Target(target)
+ {
+ }
+
+ std::string GetItemPath(const std::string& config) const override;
+
+ void AddPostExcludeFiles(
+ const std::string& config, std::set<std::string>& files,
+ cmInstallRuntimeDependencySet* set) const override;
+
+ private:
+ cmInstallTargetGenerator* Target;
+ };
+
+ class ImportedTargetItem : public Item
+ {
+ public:
+ ImportedTargetItem(cmInstallImportedRuntimeArtifactsGenerator* target)
+ : Target(target)
+ {
+ }
+
+ std::string GetItemPath(const std::string& config) const override;
+
+ private:
+ cmInstallImportedRuntimeArtifactsGenerator* Target;
+ };
+
+ void AddExecutable(std::unique_ptr<Item> executable);
+ void AddLibrary(std::unique_ptr<Item> library);
+ void AddModule(std::unique_ptr<Item> module);
+ bool AddBundleExecutable(std::unique_ptr<Item> bundleExecutable);
+
+ void AddExecutable(cmInstallTargetGenerator* executable)
+ {
+ this->AddExecutable(cm::make_unique<TargetItem>(executable));
+ }
+
+ void AddLibrary(cmInstallTargetGenerator* library)
+ {
+ this->AddLibrary(cm::make_unique<TargetItem>(library));
+ }
+
+ void AddModule(cmInstallTargetGenerator* module)
+ {
+ this->AddModule(cm::make_unique<TargetItem>(module));
+ }
+
+ bool AddBundleExecutable(cmInstallTargetGenerator* bundleExecutable)
+ {
+ return this->AddBundleExecutable(
+ cm::make_unique<TargetItem>(bundleExecutable));
+ }
+
+ void AddExecutable(cmInstallImportedRuntimeArtifactsGenerator* executable)
+ {
+ this->AddExecutable(cm::make_unique<ImportedTargetItem>(executable));
+ }
+
+ void AddLibrary(cmInstallImportedRuntimeArtifactsGenerator* library)
+ {
+ this->AddLibrary(cm::make_unique<ImportedTargetItem>(library));
+ }
+
+ void AddModule(cmInstallImportedRuntimeArtifactsGenerator* module)
+ {
+ this->AddModule(cm::make_unique<ImportedTargetItem>(module));
+ }
+
+ bool AddBundleExecutable(
+ cmInstallImportedRuntimeArtifactsGenerator* bundleExecutable)
+ {
+ return this->AddBundleExecutable(
+ cm::make_unique<ImportedTargetItem>(bundleExecutable));
+ }
+
+ const std::vector<std::unique_ptr<Item>>& GetExecutables() const
+ {
+ return this->Executables;
+ }
+
+ const std::vector<std::unique_ptr<Item>>& GetLibraries() const
+ {
+ return this->Libraries;
+ }
+
+ const std::vector<std::unique_ptr<Item>>& GetModules() const
+ {
+ return this->Modules;
+ }
+
+ Item* GetBundleExecutable() const { return this->BundleExecutable; }
+
+ bool Empty() const
+ {
+ return this->Executables.empty() && this->Libraries.empty() &&
+ this->Modules.empty();
+ }
+
+private:
+ std::string Name;
+ std::vector<std::unique_ptr<Item>> Executables;
+ std::vector<std::unique_ptr<Item>> Libraries;
+ std::vector<std::unique_ptr<Item>> Modules;
+ Item* BundleExecutable = nullptr;
+
+ std::map<const cmGeneratorTarget*, std::set<const cmGeneratorTarget*>>
+ TargetDepends;
+};
diff --git a/Source/cmInstallRuntimeDependencySetGenerator.cxx b/Source/cmInstallRuntimeDependencySetGenerator.cxx
new file mode 100644
index 000000000..44f03e1af
--- /dev/null
+++ b/Source/cmInstallRuntimeDependencySetGenerator.cxx
@@ -0,0 +1,276 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallRuntimeDependencySetGenerator.h"
+
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmGeneratorExpression.h"
+#include "cmInstallGenerator.h"
+#include "cmInstallType.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmOutputConverter.h"
+#include "cmScriptGenerator.h"
+#include "cmStringAlgorithms.h"
+#include "cmake.h"
+
+cmInstallRuntimeDependencySetGenerator::cmInstallRuntimeDependencySetGenerator(
+ DependencyType type, cmInstallRuntimeDependencySet* dependencySet,
+ std::vector<std::string> installRPaths, bool noInstallRPath,
+ std::string installNameDir, bool noInstallName, const char* depsVar,
+ const char* rpathPrefix, const char* tmpVarPrefix, std::string destination,
+ std::vector<std::string> const& configurations, std::string component,
+ std::string permissions, MessageLevel message, bool exclude_from_all,
+ cmListFileBacktrace backtrace)
+ : cmInstallGenerator(std::move(destination), configurations,
+ std::move(component), message, exclude_from_all, false,
+ std::move(backtrace))
+ , Type(type)
+ , DependencySet(dependencySet)
+ , InstallRPaths(std::move(installRPaths))
+ , NoInstallRPath(noInstallRPath)
+ , InstallNameDir(std::move(installNameDir))
+ , NoInstallName(noInstallName)
+ , Permissions(std::move(permissions))
+ , DepsVar(depsVar)
+ , RPathPrefix(rpathPrefix)
+ , TmpVarPrefix(tmpVarPrefix)
+{
+ this->ActionsPerConfig = true;
+}
+
+bool cmInstallRuntimeDependencySetGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+ return true;
+}
+
+void cmInstallRuntimeDependencySetGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ if (!this->LocalGenerator->GetMakefile()
+ ->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL")
+ .empty() &&
+ !this->NoInstallName) {
+ std::string installNameDir = "@rpath/";
+ if (!this->InstallNameDir.empty()) {
+ installNameDir = this->InstallNameDir;
+ cmGeneratorExpression::ReplaceInstallPrefix(installNameDir,
+ "${CMAKE_INSTALL_PREFIX}");
+ installNameDir = cmGeneratorExpression::Evaluate(
+ installNameDir, this->LocalGenerator, config);
+ if (installNameDir.empty()) {
+ this->LocalGenerator->GetMakefile()->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "INSTALL_NAME_DIR argument must not evaluate to an "
+ "empty string",
+ this->Backtrace);
+ return;
+ }
+ if (installNameDir.back() != '/') {
+ installNameDir += '/';
+ }
+ }
+ os << indent << "set(" << this->TmpVarPrefix << "_install_name_dir \""
+ << installNameDir << "\")\n";
+ }
+
+ os << indent << "foreach(" << this->TmpVarPrefix << "_dep IN LISTS "
+ << this->DepsVar << ")\n";
+
+ if (!this->LocalGenerator->GetMakefile()
+ ->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL")
+ .empty()) {
+ std::vector<std::string> evaluatedRPaths;
+ for (auto const& rpath : this->InstallRPaths) {
+ std::string result =
+ cmGeneratorExpression::Evaluate(rpath, this->LocalGenerator, config);
+ if (!result.empty()) {
+ evaluatedRPaths.push_back(std::move(result));
+ }
+ }
+
+ switch (this->Type) {
+ case DependencyType::Library:
+ this->GenerateAppleLibraryScript(os, config, evaluatedRPaths,
+ indent.Next());
+ break;
+ case DependencyType::Framework:
+ this->GenerateAppleFrameworkScript(os, config, evaluatedRPaths,
+ indent.Next());
+ break;
+ }
+ } else {
+ std::string depVar = cmStrCat(this->TmpVarPrefix, "_dep");
+
+ this->AddInstallRule(
+ os, this->GetDestination(config), cmInstallType_SHARED_LIBRARY, {},
+ false, this->Permissions.c_str(), nullptr, nullptr,
+ " FOLLOW_SYMLINK_CHAIN", indent.Next(), depVar.c_str());
+
+ if (this->LocalGenerator->GetMakefile()->GetSafeDefinition(
+ "CMAKE_SYSTEM_NAME") == "Linux" &&
+ !this->NoInstallRPath) {
+ std::string evaluatedRPath;
+ for (auto const& rpath : this->InstallRPaths) {
+ std::string result =
+ cmGeneratorExpression::Evaluate(rpath, this->LocalGenerator, config);
+ if (!result.empty()) {
+ if (evaluatedRPath.empty()) {
+ evaluatedRPath = std::move(result);
+ } else {
+ evaluatedRPath += ':';
+ evaluatedRPath += result;
+ }
+ }
+ }
+
+ os << indent.Next() << "get_filename_component(" << this->TmpVarPrefix
+ << "_dep_name \"${" << this->TmpVarPrefix << "_dep}\" NAME)\n";
+ if (evaluatedRPath.empty()) {
+ os << indent.Next() << "file(RPATH_REMOVE FILE \""
+ << GetDestDirPath(
+ ConvertToAbsoluteDestination(this->GetDestination(config)))
+ << "/${" << this->TmpVarPrefix << "_dep_name}\")\n";
+ } else {
+ os << indent.Next() << "file(RPATH_SET FILE \""
+ << GetDestDirPath(
+ ConvertToAbsoluteDestination(this->GetDestination(config)))
+ << "/${" << this->TmpVarPrefix << "_dep_name}\" NEW_RPATH "
+ << cmOutputConverter::EscapeForCMake(evaluatedRPath) << ")\n";
+ }
+ }
+ }
+
+ os << indent << "endforeach()\n";
+}
+
+void cmInstallRuntimeDependencySetGenerator::GenerateAppleLibraryScript(
+ std::ostream& os, const std::string& config,
+ const std::vector<std::string>& evaluatedRPaths, Indent indent)
+{
+ os << indent << "if(NOT " << this->TmpVarPrefix
+ << "_dep MATCHES \"\\\\.framework/\")\n";
+
+ auto depName = cmStrCat(this->TmpVarPrefix, "_dep");
+ this->AddInstallRule(
+ os, this->GetDestination(config), cmInstallType_SHARED_LIBRARY, {}, false,
+ this->Permissions.c_str(), nullptr, nullptr, " FOLLOW_SYMLINK_CHAIN",
+ indent.Next(), depName.c_str());
+
+ os << indent.Next() << "get_filename_component(" << this->TmpVarPrefix
+ << "_dep_name \"${" << this->TmpVarPrefix << "_dep}\" NAME)\n";
+ auto depNameVar = cmStrCat("${", this->TmpVarPrefix, "_dep_name}");
+ this->GenerateInstallNameFixup(os, config, evaluatedRPaths,
+ cmStrCat("${", this->TmpVarPrefix, "_dep}"),
+ depNameVar, indent.Next());
+
+ os << indent << "endif()\n";
+}
+
+void cmInstallRuntimeDependencySetGenerator::GenerateAppleFrameworkScript(
+ std::ostream& os, const std::string& config,
+ const std::vector<std::string>& evaluatedRPaths, Indent indent)
+{
+ os << indent << "if(" << this->TmpVarPrefix
+ << "_dep MATCHES \"^(.*/)?([^/]*\\\\.framework)/(.*)$\")\n"
+ << indent.Next() << "set(" << this->TmpVarPrefix
+ << "_dir \"${CMAKE_MATCH_1}\")\n"
+ << indent.Next() << "set(" << this->TmpVarPrefix
+ << "_name \"${CMAKE_MATCH_2}\")\n"
+ << indent.Next() << "set(" << this->TmpVarPrefix
+ << "_file \"${CMAKE_MATCH_3}\")\n"
+ << indent.Next() << "set(" << this->TmpVarPrefix << "_path \"${"
+ << this->TmpVarPrefix << "_dir}${" << this->TmpVarPrefix << "_name}\")\n";
+
+ auto depName = cmStrCat(this->TmpVarPrefix, "_path");
+ this->AddInstallRule(
+ os, this->GetDestination(config), cmInstallType_DIRECTORY, {}, false,
+ this->Permissions.c_str(), nullptr, nullptr, " USE_SOURCE_PERMISSIONS",
+ indent.Next(), depName.c_str());
+
+ auto depNameVar = cmStrCat("${", this->TmpVarPrefix, "_name}/${",
+ this->TmpVarPrefix, "_file}");
+ this->GenerateInstallNameFixup(os, config, evaluatedRPaths,
+ cmStrCat("${", this->TmpVarPrefix, "_dep}"),
+ depNameVar, indent.Next());
+
+ os << indent << "endif()\n";
+}
+
+void cmInstallRuntimeDependencySetGenerator::GenerateInstallNameFixup(
+ std::ostream& os, const std::string& config,
+ const std::vector<std::string>& evaluatedRPaths, const std::string& filename,
+ const std::string& depName, Indent indent)
+{
+ if (!(this->NoInstallRPath && this->NoInstallName)) {
+ auto indent2 = indent;
+ if (evaluatedRPaths.empty() && this->NoInstallName) {
+ indent2 = indent2.Next();
+ os << indent << "if(" << this->RPathPrefix << "_" << filename << ")\n";
+ }
+ os << indent2 << "set(" << this->TmpVarPrefix << "_rpath_args)\n";
+ if (!this->NoInstallRPath) {
+ os << indent2 << "foreach(" << this->TmpVarPrefix << "_rpath IN LISTS "
+ << this->RPathPrefix << '_' << filename << ")\n"
+ << indent2.Next() << "list(APPEND " << this->TmpVarPrefix
+ << "_rpath_args -delete_rpath \"${" << this->TmpVarPrefix
+ << "_rpath}\")\n"
+ << indent2 << "endforeach()\n";
+ }
+ os << indent2 << "execute_process(COMMAND \""
+ << this->LocalGenerator->GetMakefile()->GetSafeDefinition(
+ "CMAKE_INSTALL_NAME_TOOL")
+ << "\" ${" << this->TmpVarPrefix << "_rpath_args}\n";
+ if (!this->NoInstallRPath) {
+ for (auto const& rpath : evaluatedRPaths) {
+ os << indent2 << " -add_rpath "
+ << cmOutputConverter::EscapeForCMake(rpath) << "\n";
+ }
+ }
+ if (!this->NoInstallName) {
+ os << indent2 << " -id \"${" << this->TmpVarPrefix
+ << "_install_name_dir}" << depName << "\"\n";
+ }
+ os << indent2 << " \""
+ << GetDestDirPath(
+ ConvertToAbsoluteDestination(this->GetDestination(config)))
+ << "/" << depName << "\")\n";
+ if (evaluatedRPaths.empty() && this->NoInstallName) {
+ os << indent << "endif()\n";
+ }
+ }
+}
+
+void cmInstallRuntimeDependencySetGenerator::GenerateStripFixup(
+ std::ostream& os, const std::string& config, const std::string& depName,
+ Indent indent)
+{
+ std::string strip =
+ this->LocalGenerator->GetMakefile()->GetSafeDefinition("CMAKE_STRIP");
+ if (!strip.empty()) {
+ os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n"
+ << indent.Next() << "execute_process(COMMAND \"" << strip << "\" ";
+ if (this->LocalGenerator->GetMakefile()->GetSafeDefinition(
+ "CMAKE_HOST_SYSTEM_NAME") == "Darwin") {
+ os << "-x ";
+ }
+ os << "\""
+ << GetDestDirPath(
+ ConvertToAbsoluteDestination(this->GetDestination(config)))
+ << "/" << depName << "\")\n"
+ << indent << "endif()\n";
+ }
+}
+
+std::string cmInstallRuntimeDependencySetGenerator::GetDestination(
+ std::string const& config) const
+{
+ return cmGeneratorExpression::Evaluate(this->Destination,
+ this->LocalGenerator, config);
+}
diff --git a/Source/cmInstallRuntimeDependencySetGenerator.h b/Source/cmInstallRuntimeDependencySetGenerator.h
new file mode 100644
index 000000000..8e98b5762
--- /dev/null
+++ b/Source/cmInstallRuntimeDependencySetGenerator.h
@@ -0,0 +1,74 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
+#include "cmScriptGenerator.h"
+
+class cmInstallRuntimeDependencySet;
+class cmLocalGenerator;
+
+class cmInstallRuntimeDependencySetGenerator : public cmInstallGenerator
+{
+public:
+ enum class DependencyType
+ {
+ Library,
+ Framework,
+ };
+
+ cmInstallRuntimeDependencySetGenerator(
+ DependencyType type, cmInstallRuntimeDependencySet* dependencySet,
+ std::vector<std::string> installRPaths, bool noInstallRPath,
+ std::string installNameDir, bool noInstallName, const char* depsVar,
+ const char* rpathPrefix, const char* tmpVarPrefix, std::string destination,
+ std::vector<std::string> const& configurations, std::string component,
+ std::string permissions, MessageLevel message, bool exclude_from_all,
+ cmListFileBacktrace backtrace);
+
+ bool Compute(cmLocalGenerator* lg) override;
+
+ DependencyType GetDependencyType() const { return this->Type; }
+
+ cmInstallRuntimeDependencySet* GetRuntimeDependencySet() const
+ {
+ return this->DependencySet;
+ }
+
+ std::string GetDestination(std::string const& config) const;
+
+protected:
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) override;
+
+private:
+ DependencyType Type;
+ cmInstallRuntimeDependencySet* DependencySet;
+ std::vector<std::string> InstallRPaths;
+ bool NoInstallRPath;
+ std::string InstallNameDir;
+ bool NoInstallName;
+ std::string Permissions;
+ const char* DepsVar;
+ const char* RPathPrefix;
+ const char* TmpVarPrefix;
+ cmLocalGenerator* LocalGenerator = nullptr;
+
+ void GenerateAppleLibraryScript(
+ std::ostream& os, const std::string& config,
+ const std::vector<std::string>& evaluatedRPaths, Indent indent);
+ void GenerateAppleFrameworkScript(
+ std::ostream& os, const std::string& config,
+ const std::vector<std::string>& evaluatedRPaths, Indent indent);
+ void GenerateInstallNameFixup(
+ std::ostream& os, const std::string& config,
+ const std::vector<std::string>& evaluatedRPaths,
+ const std::string& filename, const std::string& depName, Indent indent);
+ void GenerateStripFixup(std::ostream& os, const std::string& config,
+ const std::string& depName, Indent indent);
+};
diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx
index bb389906a..bec98b6e9 100644
--- a/Source/cmInstallScriptGenerator.cxx
+++ b/Source/cmInstallScriptGenerator.cxx
@@ -14,9 +14,10 @@
cmInstallScriptGenerator::cmInstallScriptGenerator(
std::string script, bool code, std::string const& component,
- bool exclude_from_all, cmListFileBacktrace backtrace)
+ bool exclude_from_all, bool all_components, cmListFileBacktrace backtrace)
: cmInstallGenerator("", std::vector<std::string>(), component,
- MessageDefault, exclude_from_all, std::move(backtrace))
+ MessageDefault, exclude_from_all, all_components,
+ std::move(backtrace))
, Script(std::move(script))
, Code(code)
, AllowGenex(false)
diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h
index 6274f1cd2..2cf6a4b6f 100644
--- a/Source/cmInstallScriptGenerator.h
+++ b/Source/cmInstallScriptGenerator.h
@@ -21,7 +21,7 @@ class cmInstallScriptGenerator : public cmInstallGenerator
public:
cmInstallScriptGenerator(
std::string script, bool code, std::string const& component,
- bool exclude_from_all,
+ bool exclude_from_all, bool all_components,
cmListFileBacktrace backtrace = cmListFileBacktrace());
~cmInstallScriptGenerator() override;
diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx
index c333bcab2..794694ea3 100644
--- a/Source/cmInstallSubdirectoryGenerator.cxx
+++ b/Source/cmInstallSubdirectoryGenerator.cxx
@@ -17,7 +17,7 @@ cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator(
cmMakefile* makefile, std::string binaryDirectory,
cmListFileBacktrace backtrace)
: cmInstallGenerator("", std::vector<std::string>(), "", MessageDefault,
- false, std::move(backtrace))
+ false, false, std::move(backtrace))
, Makefile(makefile)
, BinaryDirectory(std::move(binaryDirectory))
{
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index bef785d0b..35165cf72 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -46,7 +46,7 @@ cmInstallTargetGenerator::cmInstallTargetGenerator(
std::string const& component, MessageLevel message, bool exclude_from_all,
bool optional, cmListFileBacktrace backtrace)
: cmInstallGenerator(dest, configurations, component, message,
- exclude_from_all, std::move(backtrace))
+ exclude_from_all, false, std::move(backtrace))
, TargetName(std::move(targetName))
, Target(nullptr)
, FilePermissions(std::move(file_permissions))
@@ -77,12 +77,15 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
}
// Tweak files located in the destination directory.
- std::string toDir = cmStrCat(this->ConvertToAbsoluteDestination(dest), '/');
+ std::string toDir = cmStrCat(ConvertToAbsoluteDestination(dest), '/');
// Add pre-installation tweaks.
if (!files.NoTweak) {
- this->AddTweak(os, indent, config, toDir, files.To,
- &cmInstallTargetGenerator::PreReplacementTweaks);
+ AddTweak(os, indent, config, toDir, files.To,
+ [this](std::ostream& o, Indent i, const std::string& c,
+ const std::string& f) {
+ this->PreReplacementTweaks(o, i, c, f);
+ });
}
// Write code to install the target file.
@@ -102,8 +105,11 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
// Add post-installation tweaks.
if (!files.NoTweak) {
- this->AddTweak(os, indent, config, toDir, files.To,
- &cmInstallTargetGenerator::PostReplacementTweaks);
+ AddTweak(os, indent, config, toDir, files.To,
+ [this](std::ostream& o, Indent i, const std::string& c,
+ const std::string& f) {
+ this->PostReplacementTweaks(o, i, c, f);
+ });
}
}
@@ -338,6 +344,7 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
// Add the names based on the current namelink mode.
if (haveNamelink) {
+ files.NamelinkMode = this->NamelinkMode;
// With a namelink we need to check the mode.
if (this->NamelinkMode == NamelinkModeOnly) {
// Install the namelink only.
@@ -460,63 +467,6 @@ bool cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
return true;
}
-void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
- const std::string& config,
- std::string const& file,
- TweakMethod tweak)
-{
- std::ostringstream tw;
- (this->*tweak)(tw, indent.Next(), config, file);
- std::string tws = tw.str();
- if (!tws.empty()) {
- os << indent << "if(EXISTS \"" << file << "\" AND\n"
- << indent << " NOT IS_SYMLINK \"" << file << "\")\n";
- os << tws;
- os << indent << "endif()\n";
- }
-}
-
-void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
- const std::string& config,
- std::string const& dir,
- std::vector<std::string> const& files,
- TweakMethod tweak)
-{
- if (files.size() == 1) {
- // Tweak a single file.
- this->AddTweak(os, indent, config,
- this->GetDestDirPath(cmStrCat(dir, files[0])), tweak);
- } else {
- // Generate a foreach loop to tweak multiple files.
- std::ostringstream tw;
- this->AddTweak(tw, indent.Next(), config, "${file}", tweak);
- std::string tws = tw.str();
- if (!tws.empty()) {
- Indent indent2 = indent.Next().Next();
- os << indent << "foreach(file\n";
- for (std::string const& f : files) {
- os << indent2 << "\"" << this->GetDestDirPath(cmStrCat(dir, f))
- << "\"\n";
- }
- os << indent2 << ")\n";
- os << tws;
- os << indent << "endforeach()\n";
- }
- }
-}
-
-std::string cmInstallTargetGenerator::GetDestDirPath(std::string const& file)
-{
- // Construct the path of the file on disk after installation on
- // which tweaks may be performed.
- std::string toDestDirPath = "$ENV{DESTDIR}";
- if (file[0] != '/' && file[0] != '$') {
- toDestDirPath += "/";
- }
- toDestDirPath += file;
- return toDestDirPath;
-}
-
void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os,
Indent indent,
const std::string& config,
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index 8c5d44410..6173f2c3e 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -39,7 +39,6 @@ public:
NamelinkModeSkip
};
void SetNamelinkMode(NamelinkModeType mode) { this->NamelinkMode = mode; }
- NamelinkModeType GetNamelinkMode() const { return this->NamelinkMode; }
std::string GetInstallFilename(const std::string& config) const;
@@ -82,6 +81,7 @@ public:
// Prefix for all files in To.
std::string ToDir;
+ NamelinkModeType NamelinkMode = NamelinkModeNone;
bool NoTweak = false;
bool UseSourcePermissions = false;
cmInstallType Type = cmInstallType();
@@ -93,15 +93,6 @@ public:
protected:
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
Indent indent) override;
- using TweakMethod = void (cmInstallTargetGenerator::*)(std::ostream&, Indent,
- const std::string&,
- const std::string&);
- void AddTweak(std::ostream& os, Indent indent, const std::string& config,
- std::string const& file, TweakMethod tweak);
- void AddTweak(std::ostream& os, Indent indent, const std::string& config,
- std::string const& dir, std::vector<std::string> const& files,
- TweakMethod tweak);
- std::string GetDestDirPath(std::string const& file);
void PreReplacementTweaks(std::ostream& os, Indent indent,
const std::string& config,
std::string const& file);
diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h
index a63347d65..6690aef84 100644
--- a/Source/cmJSONHelpers.h
+++ b/Source/cmJSONHelpers.h
@@ -239,7 +239,7 @@ cmJSONHelper<std::vector<T>, E> cmJSONVectorFilterHelper(E success, E fail,
if (!filter(t)) {
continue;
}
- out.push_back(t);
+ out.push_back(std::move(t));
}
return success;
};
diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h
index 5a90e7ec6..0863edd55 100644
--- a/Source/cmLinkItem.h
+++ b/Source/cmLinkItem.h
@@ -7,6 +7,7 @@
#include <map>
#include <ostream>
#include <string>
+#include <unordered_map>
#include <vector>
#include <cmext/algorithm>
@@ -50,6 +51,9 @@ struct cmLinkImplementationLibraries
// Libraries linked directly in this configuration.
std::vector<cmLinkImplItem> Libraries;
+ // Object files linked directly in this configuration.
+ std::vector<cmLinkItem> Objects;
+
// Libraries linked directly in other configurations.
// Needed only for OLD behavior of CMP0003.
std::vector<cmLinkItem> WrongConfigLibraries;
@@ -63,6 +67,9 @@ struct cmLinkInterfaceLibraries
// Libraries listed in the interface.
std::vector<cmLinkItem> Libraries;
+ // Object files listed in the interface.
+ std::vector<cmLinkItem> Objects;
+
// Whether the list depends on a genex referencing the head target.
bool HadHeadSensitiveCondition = false;
@@ -74,6 +81,8 @@ struct cmLinkInterface : public cmLinkInterfaceLibraries
{
// Languages whose runtime libraries must be linked.
std::vector<std::string> Languages;
+ std::unordered_map<std::string, std::vector<cmLinkItem>>
+ LanguageRuntimeLibraries;
// Shared library dependencies needed for linking on some platforms.
std::vector<cmLinkItem> SharedDeps;
@@ -109,6 +118,8 @@ struct cmLinkImplementation : public cmLinkImplementationLibraries
{
// Languages whose runtime libraries must be linked.
std::vector<std::string> Languages;
+ std::unordered_map<std::string, std::vector<cmLinkImplItem>>
+ LanguageRuntimeLibraries;
// Whether the list depends on a link language genex.
bool HadLinkLanguageSensitiveCondition = false;
diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx
index 480c005cd..5646368b7 100644
--- a/Source/cmLinkLineComputer.cxx
+++ b/Source/cmLinkLineComputer.cxx
@@ -11,10 +11,8 @@
#include "cmGeneratorTarget.h"
#include "cmListFileCache.h"
#include "cmOutputConverter.h"
-#include "cmStateDirectory.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
-#include "cmSystemTools.h"
cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
cmStateDirectory const& stateDir)
@@ -52,13 +50,7 @@ void cmLinkLineComputer::SetRelink(bool relink)
std::string cmLinkLineComputer::ConvertToLinkReference(
std::string const& lib) const
{
- std::string relLib = lib;
-
- if (this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), lib)) {
- relLib = cmSystemTools::ForceToRelativePath(
- this->StateDir.GetCurrentBinary(), lib);
- }
- return relLib;
+ return this->OutputConverter->MaybeRelativeToCurBinDir(lib);
}
std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
@@ -82,8 +74,12 @@ void cmLinkLineComputer::ComputeLinkLibs(
}
BT<std::string> linkLib;
- if (item.IsPath) {
- linkLib.Value += cli.GetLibLinkFileFlag();
+ if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
+ if (item.IsObject == cmComputeLinkInformation::ItemIsObject::Yes) {
+ linkLib.Value += cli.GetObjLinkFileFlag();
+ } else {
+ linkLib.Value += cli.GetLibLinkFileFlag();
+ }
linkLib.Value += this->ConvertToOutputFormat(
this->ConvertToLinkReference(item.Value.Value));
linkLib.Backtrace = item.Value.Backtrace;
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 9cae92669..2ffff96b9 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -111,7 +111,7 @@ void cmLinkLineDeviceComputer::ComputeLinkLibraries(
}
BT<std::string> linkLib;
- if (item.IsPath) {
+ if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
// nvcc understands absolute paths to libraries ending in '.a' or '.lib'.
// These should be passed to nvlink. Other extensions need to be left
// out because nvlink may not understand or need them. Even though it
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index fdddb4556..09cd88e08 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -4,9 +4,7 @@
#include <algorithm>
#include <cassert>
-#include <cstddef>
#include <cstdio>
-#include <cstdlib> // required for atoi
#include <functional>
#include <iterator>
#include <set>
@@ -36,6 +34,42 @@
namespace {
+bool GetIndexArg(const std::string& arg, int* idx, cmMakefile& mf)
+{
+ long value;
+ if (!cmStrToLong(arg, &value)) {
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0121)) {
+ case cmPolicies::WARN: {
+ // Default is to warn and use old behavior OLD behavior is to allow
+ // compatibility, so issue a warning and use the previous behavior.
+ std::string warn =
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0121),
+ " Invalid list index \"", arg, "\".");
+ mf.IssueMessage(MessageType::AUTHOR_WARNING, warn);
+ break;
+ }
+ case cmPolicies::OLD:
+ // OLD behavior is to allow compatibility, so just ignore the
+ // situation.
+ break;
+ case cmPolicies::NEW:
+ return false;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ std::string msg =
+ cmStrCat(cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0121),
+ " Invalid list index \"", arg, "\".");
+ mf.IssueMessage(MessageType::FATAL_ERROR, msg);
+ break;
+ }
+ }
+
+ // Truncation is happening here, but it had always been happening here.
+ *idx = static_cast<int>(value);
+
+ return true;
+}
+
bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
std::string const& listName,
std::vector<std::string>& varArgsExpanded,
@@ -154,7 +188,11 @@ bool HandleGetCommand(std::vector<std::string> const& args,
const char* sep = "";
size_t nitem = varArgsExpanded.size();
for (cc = 2; cc < args.size() - 1; cc++) {
- int item = atoi(args[cc].c_str());
+ int item;
+ if (!GetIndexArg(args[cc], &item, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[cc], " is not a valid index"));
+ return false;
+ }
value += sep;
sep = ";";
if (item < 0) {
@@ -362,7 +400,11 @@ bool HandleInsertCommand(std::vector<std::string> const& args,
const std::string& listName = args[1];
// expand the variable
- int item = atoi(args[2].c_str());
+ int item;
+ if (!GetIndexArg(args[2], &item, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[2], " is not a valid index"));
+ return false;
+ }
std::vector<std::string> varArgsExpanded;
if ((!GetList(varArgsExpanded, listName, status.GetMakefile()) ||
varArgsExpanded.empty()) &&
@@ -1282,8 +1324,16 @@ bool HandleSublistCommand(std::vector<std::string> const& args,
return true;
}
- const int start = atoi(args[2].c_str());
- const int length = atoi(args[3].c_str());
+ int start;
+ int length;
+ if (!GetIndexArg(args[2], &start, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[2], " is not a valid index"));
+ return false;
+ }
+ if (!GetIndexArg(args[3], &length, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[3], " is not a valid index"));
+ return false;
+ }
using size_type = decltype(varArgsExpanded)::size_type;
@@ -1338,7 +1388,11 @@ bool HandleRemoveAtCommand(std::vector<std::string> const& args,
std::vector<size_t> removed;
size_t nitem = varArgsExpanded.size();
for (cc = 2; cc < args.size(); ++cc) {
- int item = atoi(args[cc].c_str());
+ int item;
+ if (!GetIndexArg(args[cc], &item, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[cc], " is not a valid index"));
+ return false;
+ }
if (item < 0) {
item = static_cast<int>(nitem) + item;
}
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 1464a14cc..4f7c95944 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -7,11 +7,14 @@
#include <sstream>
#include <utility>
+#ifdef _WIN32
+# include <cmsys/Encoding.hxx>
+#endif
+
#include "cmListFileLexer.h"
#include "cmMessageType.h"
#include "cmMessenger.h"
#include "cmState.h"
-#include "cmStateDirectory.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -83,9 +86,15 @@ bool cmListFileParser::ParseFile(const char* filename)
{
this->FileName = filename;
+#ifdef _WIN32
+ std::string expandedFileName = cmsys::Encoding::ToNarrow(
+ cmSystemTools::ConvertToWindowsExtendedPath(filename));
+ filename = expandedFileName.c_str();
+#endif
+
// Open the file.
cmListFileLexer_BOM bom;
- if (!cmListFileLexer_SetFileName(this->Lexer, this->FileName, &bom)) {
+ if (!cmListFileLexer_SetFileName(this->Lexer, filename, &bom)) {
this->IssueFileOpenError("cmListFileCache: error can not open file.");
return false;
}
@@ -540,7 +549,7 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) const
cmListFileContext lfc = this->TopEntry->Context;
cmStateSnapshot bottom = this->GetBottom();
if (!bottom.GetState()->GetIsInTryCompile()) {
- lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
+ lfc.FilePath = cmSystemTools::RelativeIfUnder(
bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
out << (lfc.Line ? " at " : " in ") << lfc;
@@ -571,7 +580,7 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
}
cmListFileContext lfc = cur->Context;
if (!bottom.GetState()->GetIsInTryCompile()) {
- lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
+ lfc.FilePath = cmSystemTools::RelativeIfUnder(
bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
out << " " << lfc << "\n";
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index 2981ef877..2456db9fe 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -90,6 +90,9 @@ struct LoadedCommandImpl : cmLoadedCommandInfo
{
if (this->Destructor) {
SignalHandlerGuard guard(this->Name);
+#if defined(__NVCOMPILER)
+ static_cast<void>(guard); // convince compiler var is used
+#endif
this->Destructor(this);
}
if (this->Error != nullptr) {
@@ -103,12 +106,18 @@ struct LoadedCommandImpl : cmLoadedCommandInfo
int DoInitialPass(cmMakefile* mf, int argc, char* argv[])
{
SignalHandlerGuard guard(this->Name);
+#if defined(__NVCOMPILER)
+ static_cast<void>(guard); // convince compiler var is used
+#endif
return this->InitialPass(this, mf, argc, argv);
}
void DoFinalPass(cmMakefile* mf)
{
SignalHandlerGuard guard(this->Name);
+#if defined(__NVCOMPILER)
+ static_cast<void>(guard); // convince compiler var is used
+#endif
this->FinalPass(this, mf);
}
};
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
index 5daaeff49..211525a26 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -9,14 +9,17 @@
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmProperty.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
class cmGlobalGenerator;
cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
- cmMakefile* mf, std::string wd)
+ cmMakefile* mf, WorkDir wd)
: cmLocalGenerator(gg, mf)
- , WorkingDirectory(std::move(wd))
+ , WorkingDirectory(wd)
{
this->ConfigNames =
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
@@ -24,6 +27,23 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
cmLocalCommonGenerator::~cmLocalCommonGenerator() = default;
+std::string const& cmLocalCommonGenerator::GetWorkingDirectory() const
+{
+ if (this->WorkingDirectory == WorkDir::TopBin) {
+ return this->GetState()->GetBinaryDirectory();
+ }
+ return this->StateSnapshot.GetDirectory().GetCurrentBinary();
+}
+
+std::string cmLocalCommonGenerator::MaybeRelativeToWorkDir(
+ std::string const& path) const
+{
+ if (this->WorkingDirectory == WorkDir::TopBin) {
+ return this->MaybeRelativeToTopBinDir(path);
+ }
+ return this->MaybeRelativeToCurBinDir(path);
+}
+
std::string cmLocalCommonGenerator::GetTargetFortranFlags(
cmGeneratorTarget const* target, std::string const& config)
{
@@ -35,11 +55,10 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
// Add a module output directory flag if necessary.
std::string mod_dir =
- target->GetFortranModuleDirectory(this->WorkingDirectory);
+ target->GetFortranModuleDirectory(this->GetWorkingDirectory());
if (!mod_dir.empty()) {
mod_dir = this->ConvertToOutputFormat(
- this->MaybeConvertToRelativePath(this->WorkingDirectory, mod_dir),
- cmOutputConverter::SHELL);
+ this->MaybeRelativeToWorkDir(mod_dir), cmOutputConverter::SHELL);
} else {
mod_dir =
this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h
index f1eaf61fa..0505c138d 100644
--- a/Source/cmLocalCommonGenerator.h
+++ b/Source/cmLocalCommonGenerator.h
@@ -20,9 +20,15 @@ class cmSourceFile;
*/
class cmLocalCommonGenerator : public cmLocalGenerator
{
+protected:
+ enum class WorkDir
+ {
+ TopBin,
+ CurBin,
+ };
+
public:
- cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf,
- std::string wd);
+ cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf, WorkDir wd);
~cmLocalCommonGenerator() override;
std::vector<std::string> const& GetConfigNames() const
@@ -30,7 +36,9 @@ public:
return this->ConfigNames;
}
- std::string GetWorkingDirectory() const { return this->WorkingDirectory; }
+ std::string const& GetWorkingDirectory() const;
+
+ std::string MaybeRelativeToWorkDir(std::string const& path) const;
std::string GetTargetFortranFlags(cmGeneratorTarget const* target,
std::string const& config) override;
@@ -40,7 +48,7 @@ public:
cmGeneratorTarget const* gt = nullptr) override;
protected:
- std::string WorkingDirectory;
+ WorkDir WorkingDirectory;
std::vector<std::string> ConfigNames;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index dcf590a14..3b282de98 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -88,7 +88,6 @@ static auto ruleReplaceVars = { "CMAKE_${LANG}_COMPILER",
cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
: cmOutputConverter(makefile->GetStateSnapshot())
- , StateSnapshot(makefile->GetStateSnapshot())
, DirectoryBacktrace(makefile->GetBacktrace())
{
this->GlobalGenerator = gg;
@@ -351,11 +350,10 @@ void cmLocalGenerator::GenerateTestFiles()
}
using vec_t = std::vector<cmStateSnapshot>;
vec_t const& children = this->Makefile->GetStateSnapshot().GetChildren();
- std::string parentBinDir = this->GetCurrentBinaryDirectory();
for (cmStateSnapshot const& i : children) {
// TODO: Use add_subdirectory instead?
std::string outP = i.GetDirectory().GetCurrentBinary();
- outP = this->MaybeConvertToRelativePath(parentBinDir, outP);
+ outP = this->MaybeRelativeToCurBinDir(outP);
outP = cmOutputConverter::EscapeForCMake(outP);
fout << "subdirs(" << outP << ")\n";
}
@@ -782,9 +780,9 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures()
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
using LanguagePair = std::pair<std::string, std::string>;
- std::vector<LanguagePair> pairedLanguages{ { "OBJC", "C" },
- { "OBJCXX", "CXX" },
- { "CUDA", "CXX" } };
+ std::vector<LanguagePair> pairedLanguages{
+ { "OBJC", "C" }, { "OBJCXX", "CXX" }, { "CUDA", "CXX" }, { "HIP", "CXX" }
+ };
std::set<LanguagePair> inferredEnabledLanguages;
for (auto const& lang : pairedLanguages) {
if (this->Makefile->GetState()->GetLanguageEnabled(lang.first)) {
@@ -838,16 +836,16 @@ cmProp cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
}
std::string cmLocalGenerator::ConvertToIncludeReference(
- std::string const& path, OutputFormat format, bool forceFullPaths)
+ std::string const& path, IncludePathStyle pathStyle, OutputFormat format)
{
- static_cast<void>(forceFullPaths);
+ static_cast<void>(pathStyle);
return this->ConvertToOutputForExisting(path, format);
}
std::string cmLocalGenerator::GetIncludeFlags(
- const std::vector<std::string>& includeDirs, cmGeneratorTarget* target,
- const std::string& lang, bool forceFullPaths, bool forResponseFile,
- const std::string& config)
+ std::vector<std::string> const& includeDirs, cmGeneratorTarget* target,
+ std::string const& lang, std::string const& config, bool forResponseFile,
+ IncludePathStyle pathStyle)
{
if (lang.empty()) {
return "";
@@ -923,7 +921,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
flagUsed = true;
}
std::string includePath =
- this->ConvertToIncludeReference(i, shellFormat, forceFullPaths);
+ this->ConvertToIncludeReference(i, pathStyle, shellFormat);
if (quotePaths && !includePath.empty() && includePath.front() != '\"') {
includeFlags << "\"";
}
@@ -1406,8 +1404,8 @@ void cmLocalGenerator::GetDeviceLinkFlags(
linkLineComputer->GetLinkerLanguage(target, config);
if (pcli) {
- // Compute the required cuda device link libraries when
- // resolving cuda device symbols
+ // Compute the required device link libraries when
+ // resolving gpu lang device symbols
this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath,
linkPath);
}
@@ -1527,12 +1525,12 @@ void cmLocalGenerator::GetTargetFlags(
}
if (target->IsWin32Executable(config)) {
- exeFlags +=
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE");
+ exeFlags += this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE"));
exeFlags += " ";
} else {
- exeFlags +=
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
+ exeFlags += this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_CONSOLE_EXE"));
exeFlags += " ";
}
@@ -1970,9 +1968,11 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
compilerSimulateId =
this->Makefile->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID");
}
+ } else if (lang == "HIP") {
+ target->AddHIPArchitectureFlags(flags);
}
- // Add VFS Overlay for Clang compiliers
+ // Add VFS Overlay for Clang compilers
if (compiler == "Clang") {
if (cmProp vfsOverlay =
this->Makefile->GetDefinition("CMAKE_CLANG_VFS_OVERLAY")) {
@@ -2307,13 +2307,6 @@ void cmLocalGenerator::AddCMP0018Flags(std::string& flags,
if (this->GetShouldUseOldFlags(shared, lang)) {
this->AddSharedFlags(flags, lang, shared);
} else {
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE")) {
- this->AddPositionIndependentFlags(flags, lang, targetType);
- }
- return;
- }
-
if (target->GetLinkInterfaceDependentBoolProperty(
"POSITION_INDEPENDENT_CODE", config)) {
this->AddPositionIndependentFlags(flags, lang, targetType);
@@ -2438,7 +2431,7 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
}
cmProp ispcHeaderSuffixProp = target->GetProperty("ISPC_HEADER_SUFFIX");
- assert(ispcHeaderSuffixProp != nullptr);
+ assert(ispcHeaderSuffixProp);
std::vector<std::string> ispcArchSuffixes =
detail::ComputeISPCObjectSuffixes(target);
@@ -2701,8 +2694,9 @@ void cmLocalGenerator::CopyPchCompilePdb(
}
file << "foreach(retry RANGE 1 30)\n";
- file << " if (EXISTS \"" << from_file << "\" AND \"" << from_file
- << " \" IS_NEWER_THAN \"" << dest_file << "\")\n";
+ file << " if (EXISTS \"" << from_file << "\" AND (NOT EXISTS \""
+ << dest_file << "\" OR NOT \"" << dest_file << " \" IS_NEWER_THAN \""
+ << from_file << "\"))\n";
file << " execute_process(COMMAND ${CMAKE_COMMAND} -E copy";
file << " \"" << from_file << "\""
<< " \"" << to_dir << "\" RESULT_VARIABLE result "
@@ -2785,7 +2779,7 @@ void cmLocalGenerator::IncludeFileInUnitySources(
cmGeneratedFileStream& unity_file, std::string const& sf_full_path,
cmProp beforeInclude, cmProp afterInclude, cmProp uniqueIdName) const
{
- if (uniqueIdName && !uniqueIdName->empty()) {
+ if (cmNonempty(uniqueIdName)) {
std::string pathToHash;
auto PathEqOrSubDir = [](std::string const& a, std::string const& b) {
return (cmSystemTools::ComparePath(a, b) ||
@@ -3000,7 +2994,7 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO";
cmProp rawFlagsList = this->Makefile->GetDefinition(name);
- if (rawFlagsList == nullptr) {
+ if (!rawFlagsList) {
return;
}
@@ -3239,7 +3233,7 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags,
{
cmProp optionList = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_", feature));
- if (optionList != nullptr) {
+ if (optionList) {
std::vector<std::string> options = cmExpandedList(*optionList);
for (std::string const& o : options) {
this->AppendFlagEscape(flags, o);
@@ -3285,10 +3279,9 @@ std::string cmLocalGenerator::ConstructComment(
std::string comment;
comment = "Generating ";
const char* sep = "";
- std::string currentBinaryDir = this->GetCurrentBinaryDirectory();
for (std::string const& o : ccg.GetOutputs()) {
comment += sep;
- comment += this->MaybeConvertToRelativePath(currentBinaryDir, o);
+ comment += this->MaybeRelativeToCurBinDir(o);
sep = ", ";
}
return comment;
@@ -3326,7 +3319,7 @@ void cmLocalGenerator::GenerateTargetInstallRules(
// Include the user-specified pre-install script for this target.
if (cmProp preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) {
- cmInstallScriptGenerator g(*preinstall, false, "", false);
+ cmInstallScriptGenerator g(*preinstall, false, "", false, false);
g.Generate(os, config, configurationTypes);
}
@@ -3379,7 +3372,7 @@ void cmLocalGenerator::GenerateTargetInstallRules(
// Include the user-specified post-install script for this target.
if (cmProp postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) {
- cmInstallScriptGenerator g(*postinstall, false, "", false);
+ cmInstallScriptGenerator g(*postinstall, false, "", false, false);
g.Generate(os, config, configurationTypes);
}
}
@@ -3540,6 +3533,21 @@ bool cmLocalGenerator::IsNinjaMulti() const
return this->GetState()->UseNinjaMulti();
}
+namespace {
+std::string relativeIfUnder(std::string const& top, std::string const& cur,
+ std::string const& path)
+{
+ // Use a path relative to 'cur' if it can be expressed without
+ // a `../` sequence that leaves 'top'.
+ if (cmSystemTools::IsSubDirectory(path, cur) ||
+ (cmSystemTools::IsSubDirectory(cur, top) &&
+ cmSystemTools::IsSubDirectory(path, top))) {
+ return cmSystemTools::ForceToRelativePath(cur, path);
+ }
+ return path;
+}
+}
+
std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
const cmSourceFile& source, std::string const& dir_max,
bool* hasSourceExtension, char const* customOutputExtension)
@@ -3549,15 +3557,15 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
std::string const& fullPath = source.GetFullPath();
// Try referencing the source relative to the source tree.
- std::string relFromSource = this->MaybeConvertToRelativePath(
- this->GetCurrentSourceDirectory(), fullPath);
+ std::string relFromSource = relativeIfUnder(
+ this->GetSourceDirectory(), this->GetCurrentSourceDirectory(), fullPath);
assert(!relFromSource.empty());
bool relSource = !cmSystemTools::FileIsFullPath(relFromSource);
bool subSource = relSource && relFromSource[0] != '.';
// Try referencing the source relative to the binary tree.
- std::string relFromBinary = this->MaybeConvertToRelativePath(
- this->GetCurrentBinaryDirectory(), fullPath);
+ std::string relFromBinary = relativeIfUnder(
+ this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory(), fullPath);
assert(!relFromBinary.empty());
bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary);
bool subBinary = relBinary && relFromBinary[0] != '.';
@@ -3672,13 +3680,6 @@ std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const
return this->StateSnapshot.GetDirectory().GetCurrentSource();
}
-std::string cmLocalGenerator::MaybeConvertToRelativePath(
- std::string const& local_path, std::string const& remote_path) const
-{
- return this->StateSnapshot.GetDirectory().ConvertToRelPathIfNotContained(
- local_path, remote_path);
-}
-
std::string cmLocalGenerator::GetTargetDirectory(
const cmGeneratorTarget* /*unused*/) const
{
@@ -3930,7 +3931,7 @@ std::string ComputeCustomCommandRuleFileName(cmLocalGenerator& lg,
// The output path contains a generator expression, but we must choose
// a single source file path to which to attach the custom command.
- // Use some heuristics to provie a nice-looking name when possible.
+ // Use some heuristics to provide a nice-looking name when possible.
// If the only genex is $<CONFIG>, replace that gracefully.
{
@@ -4097,6 +4098,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
cc.SetDepfile(depfile);
cc.SetJobPool(job_pool);
cc.SetCMP0116Status(cmp0116);
+ cc.SetTarget(target->GetName());
switch (type) {
case cmCustomCommandType::PRE_BUILD:
target->AddPreBuildCommand(std::move(cc));
@@ -4218,7 +4220,7 @@ std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target)
auto pos = ispcTarget.find('-');
auto target_suffix = ispcTarget.substr(0, pos);
if (target_suffix ==
- "avx1") { // when targetting avx1 ISPC uses the 'avx' output string
+ "avx1") { // when targeting avx1 ISPC uses the 'avx' output string
target_suffix = "avx";
}
ispcTarget = target_suffix;
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index e48849a57..993280ac2 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -171,13 +171,19 @@ public:
cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
+
+ enum class IncludePathStyle
+ {
+ Default,
+ Absolute,
+ };
+
//! Get the include flags for the current makefile and language
- std::string GetIncludeFlags(const std::vector<std::string>& includes,
- cmGeneratorTarget* target,
- const std::string& lang,
- bool forceFullPaths = false,
- bool forResponseFile = false,
- const std::string& config = "");
+ std::string GetIncludeFlags(
+ std::vector<std::string> const& includes, cmGeneratorTarget* target,
+ std::string const& lang, std::string const& config,
+ bool forResponseFile = false,
+ IncludePathStyle pathStyle = IncludePathStyle::Default);
using GeneratorTargetVector =
std::vector<std::unique_ptr<cmGeneratorTarget>>;
@@ -256,11 +262,6 @@ public:
bool GetRealDependency(const std::string& name, const std::string& config,
std::string& dep);
- virtual std::string ConvertToIncludeReference(
- std::string const& path,
- cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL,
- bool forceFullPaths = false);
-
/** Called from command-line hook to clear dependencies. */
virtual void ClearDependencies(cmMakefile* /* mf */, bool /* verbose */) {}
@@ -462,16 +463,6 @@ public:
std::string const& GetCurrentSourceDirectory() const;
/**
- * Convert the given remote path to a relative path with respect to
- * the given local path. Both paths must use forward slashes and not
- * already be escaped or quoted.
- * The conversion is skipped if the paths are not both in the source
- * or both in the binary tree.
- */
- std::string MaybeConvertToRelativePath(std::string const& local_path,
- std::string const& remote_path) const;
-
- /**
* Generate a macOS application bundle Info.plist file.
*/
void GenerateAppleInfoPList(cmGeneratorTarget* target,
@@ -557,6 +548,13 @@ public:
cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop);
protected:
+ // The default implementation ignores the IncludePathStyle and always
+ // uses absolute paths. A generator may override this to use relative
+ // paths in some cases.
+ virtual std::string ConvertToIncludeReference(
+ std::string const& path, IncludePathStyle pathStyle,
+ cmOutputConverter::OutputFormat format);
+
//! put all the libraries for a target on into the given stream
void OutputLinkLibraries(cmComputeLinkInformation* pcli,
cmLinkLineComputer* linkLineComputer,
@@ -583,7 +581,6 @@ protected:
virtual bool CheckDefinition(std::string const& define) const;
cmMakefile* Makefile;
- cmStateSnapshot StateSnapshot;
cmListFileBacktrace DirectoryBacktrace;
cmGlobalGenerator* GlobalGenerator;
std::map<std::string, std::string> UniqueObjectNamesMap;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 081cc41fc..7f7b1e7d7 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -39,7 +39,7 @@
cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
cmMakefile* mf)
- : cmLocalCommonGenerator(gg, mf, mf->GetState()->GetBinaryDirectory())
+ : cmLocalCommonGenerator(gg, mf, WorkDir::TopBin)
{
}
@@ -60,8 +60,8 @@ void cmLocalNinjaGenerator::Generate()
{
// Compute the path to use when referencing the current output
// directory from the top output directory.
- this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath(
- this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
+ this->HomeRelativeOutputPath =
+ this->MaybeRelativeToTopBinDir(this->GetCurrentBinaryDirectory());
if (this->HomeRelativeOutputPath == ".") {
this->HomeRelativeOutputPath.clear();
}
@@ -97,9 +97,12 @@ void cmLocalNinjaGenerator::Generate()
// 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) {
+ 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
@@ -202,17 +205,12 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
// Virtual protected methods.
std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
- std::string const& path, cmOutputConverter::OutputFormat format,
- bool forceFullPaths)
+ std::string const& path, IncludePathStyle pathStyle,
+ cmOutputConverter::OutputFormat format)
{
- if (forceFullPaths) {
- return this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(path, this->GetCurrentBinaryDirectory()),
- format);
- }
- return this->ConvertToOutputFormat(
- this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), path),
- format);
+ // FIXME: Remove IncludePathStyle infrastructure. It is no longer used.
+ static_cast<void>(pathStyle);
+ return this->ConvertToOutputFormat(path, format);
}
// Private methods.
@@ -261,6 +259,7 @@ void cmLocalNinjaGenerator::WriteBuildFileTop()
this->GetConfigNames().front());
}
this->WriteNinjaFilesInclusionCommon(this->GetCommonFileStream());
+ this->WriteNinjaWorkDir(this->GetCommonFileStream());
// For the rule file.
this->WriteProjectHeader(this->GetRulesFileStream());
@@ -362,6 +361,17 @@ void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os)
os << "\n";
}
+void cmLocalNinjaGenerator::WriteNinjaWorkDir(std::ostream& os)
+{
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ cmGlobalNinjaGenerator::WriteComment(
+ os, "Logical path to working directory; prefix for absolute paths.");
+ cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
+ std::string ninja_workdir = this->GetBinaryDirectory();
+ ng->StripNinjaOutputPathPrefixAsSuffix(ninja_workdir); // Also appends '/'.
+ os << "cmake_ninja_workdir = " << ng->EncodePath(ninja_workdir) << "\n";
+}
+
void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
@@ -636,16 +646,11 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
}
}
- cmNinjaDeps ninjaOutputs(outputs.size() + byproducts.size());
- std::transform(outputs.begin(), outputs.end(), ninjaOutputs.begin(),
- gg->MapToNinjaPath());
- std::transform(byproducts.begin(), byproducts.end(),
- ninjaOutputs.begin() + outputs.size(),
- gg->MapToNinjaPath());
+ cmGlobalNinjaGenerator::CCOutputs ccOutputs(gg);
+ ccOutputs.Add(outputs);
+ ccOutputs.Add(byproducts);
- for (std::string const& ninjaOutput : ninjaOutputs) {
- gg->SeenCustomCommandOutput(ninjaOutput);
- }
+ std::string mainOutput = ccOutputs.ExplicitOuts[0];
cmNinjaDeps ninjaDeps;
this->AppendCustomCommandDeps(ccg, ninjaDeps, fileConfig);
@@ -655,13 +660,14 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
if (cmdLines.empty()) {
cmNinjaBuild build("phony");
- build.Comment = "Phony custom command for " + ninjaOutputs[0];
- build.Outputs = std::move(ninjaOutputs);
+ build.Comment = cmStrCat("Phony custom command for ", mainOutput);
+ build.Outputs = std::move(ccOutputs.ExplicitOuts);
+ build.WorkDirOuts = std::move(ccOutputs.WorkDirOuts);
build.ExplicitDeps = std::move(ninjaDeps);
build.OrderOnlyDeps = orderOnlyDeps;
gg->WriteBuild(this->GetImplFileStream(fileConfig), build);
} else {
- std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
+ std::string customStep = cmSystemTools::GetFilenameName(mainOutput);
if (this->GlobalGenerator->IsMultiConfig()) {
customStep += '-';
customStep += fileConfig;
@@ -671,9 +677,9 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
// Hash full path to make unique.
customStep += '-';
cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
- customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+ customStep += hash.HashString(mainOutput).substr(0, 7);
- std::string depfile = cc->GetDepfile();
+ std::string depfile = ccg.GetDepfile();
if (!depfile.empty()) {
switch (cc->GetCMP0116Status()) {
case cmPolicies::WARN:
@@ -692,20 +698,19 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
- cmSystemTools::MakeDirectory(
- cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles/d"));
depfile = ccg.GetInternalDepfile();
break;
}
}
+ std::string comment = cmStrCat("Custom command for ", mainOutput);
gg->WriteCustomCommandBuild(
this->BuildCommandLine(cmdLines, ccg.GetOutputConfig(), fileConfig,
customStep),
- this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
- depfile, cc->GetJobPool(), cc->GetUsesTerminal(),
- /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig,
- ninjaDeps, orderOnlyDeps);
+ this->ConstructComment(ccg), comment, depfile, cc->GetJobPool(),
+ cc->GetUsesTerminal(),
+ /*restat*/ !symbolic || !byproducts.empty(), fileConfig,
+ std::move(ccOutputs), std::move(ninjaDeps), std::move(orderOnlyDeps));
}
}
}
@@ -878,8 +883,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
if (!outputs.empty()) {
output = outputs[0];
if (ccg.GetWorkingDirectory().empty()) {
- output = this->MaybeConvertToRelativePath(
- this->GetCurrentBinaryDirectory(), output);
+ output = this->MaybeRelativeToCurBinDir(output);
}
output = this->ConvertToOutputFormat(output, cmOutputConverter::SHELL);
}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 0734c5cad..64040374e 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -12,6 +12,7 @@
#include "cmListFileCache.h"
#include "cmLocalCommonGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmNinjaTypes.h"
#include "cmOutputConverter.h"
@@ -92,9 +93,8 @@ public:
protected:
std::string ConvertToIncludeReference(
- std::string const& path,
- cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL,
- bool forceFullPaths = false) override;
+ std::string const& path, IncludePathStyle pathStyle,
+ cmOutputConverter::OutputFormat format) override;
private:
cmGeneratedFileStream& GetImplFileStream(const std::string& config) const;
@@ -108,6 +108,7 @@ private:
const std::string& config);
void WriteNinjaFilesInclusionConfig(std::ostream& os);
void WriteNinjaFilesInclusionCommon(std::ostream& os);
+ void WriteNinjaWorkDir(std::ostream& os);
void WriteProcessedMakefile(std::ostream& os);
void WritePools(std::ostream& os);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 464df6854..0667c55a3 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -38,7 +38,6 @@
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
-#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -110,7 +109,7 @@ private:
cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3(
cmGlobalGenerator* gg, cmMakefile* mf)
- : cmLocalCommonGenerator(gg, mf, mf->GetCurrentBinaryDirectory())
+ : cmLocalCommonGenerator(gg, mf, WorkDir::CurBin)
{
this->MakefileVariableSize = 0;
this->ColorMakefile = false;
@@ -177,8 +176,8 @@ void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath()
{
// Compute the path to use when referencing the current output
// directory from the top output directory.
- this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath(
- this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
+ this->HomeRelativeOutputPath =
+ this->MaybeRelativeToTopBinDir(this->GetCurrentBinaryDirectory());
if (this->HomeRelativeOutputPath == ".") {
this->HomeRelativeOutputPath.clear();
}
@@ -290,9 +289,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
for (LocalObjectEntry const& entry : localObjectFile.second) {
if (entry.Language == "C" || entry.Language == "CXX" ||
entry.Language == "CUDA" || entry.Language == "Fortran" ||
- entry.Language == "ISPC") {
- // Right now, C, C++, Fortran and CUDA have both a preprocessor and the
- // ability to generate assembly code
+ entry.Language == "HIP" || entry.Language == "ISPC") {
+ // Right now, C, C++, CUDA, Fortran, HIP and ISPC have both a
+ // preprocessor and the ability to generate assembly code
lang_has_preprocessor = true;
lang_has_assembly = true;
break;
@@ -474,11 +473,9 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
infoFileStream
<< "# Relative path conversion top directories.\n"
<< "set(CMAKE_RELATIVE_PATH_TOP_SOURCE \""
- << this->StateSnapshot.GetDirectory().GetRelativePathTopSource()
- << "\")\n"
+ << this->GetRelativePathTopSource() << "\")\n"
<< "set(CMAKE_RELATIVE_PATH_TOP_BINARY \""
- << this->StateSnapshot.GetDirectory().GetRelativePathTopBinary()
- << "\")\n"
+ << this->GetRelativePathTopBinary() << "\")\n"
<< "\n";
/* clang-format on */
@@ -561,8 +558,8 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
}
// Construct the left hand side of the rule.
- std::string tgt = this->ConvertToMakefilePath(
- this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), target));
+ std::string tgt =
+ this->ConvertToMakefilePath(this->MaybeRelativeToTopBinDir(target));
const char* space = "";
if (tgt.size() == 1) {
@@ -586,11 +583,9 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
} else {
// Split dependencies into multiple rule lines. This allows for
// very long dependency lists even on older make implementations.
- std::string binDir = this->GetBinaryDirectory();
for (std::string const& depend : depends) {
os << tgt << space << ": "
- << this->ConvertToMakefilePath(
- this->MaybeConvertToRelativePath(binDir, depend))
+ << this->ConvertToMakefilePath(this->MaybeRelativeToTopBinDir(depend))
<< '\n';
}
}
@@ -968,7 +963,6 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
// Add each command line to the set of commands.
std::vector<std::string> commands1;
- std::string currentBinDir = this->GetCurrentBinaryDirectory();
for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
// Build the command line in a single string.
std::string cmd = ccg.GetCommand(c);
@@ -993,7 +987,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
// working directory will be the start-output directory.
bool had_slash = cmd.find('/') != std::string::npos;
if (workingDir.empty()) {
- cmd = this->MaybeConvertToRelativePath(currentBinDir, cmd);
+ cmd = this->MaybeRelativeToCurBinDir(cmd);
}
bool has_slash = cmd.find('/') != std::string::npos;
if (had_slash && !has_slash) {
@@ -1017,8 +1011,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
if (!outputs.empty()) {
output = outputs[0];
if (workingDir.empty()) {
- output = this->MaybeConvertToRelativePath(
- this->GetCurrentBinaryDirectory(), output);
+ output = this->MaybeRelativeToCurBinDir(output);
}
output =
this->ConvertToOutputFormat(output, cmOutputConverter::SHELL);
@@ -1097,18 +1090,16 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
if (!files.empty()) {
fout << "file(REMOVE_RECURSE\n";
for (std::string const& file : files) {
- std::string fc = this->MaybeConvertToRelativePath(currentBinDir, file);
+ std::string fc = this->MaybeRelativeToCurBinDir(file);
fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n";
}
fout << ")\n";
}
{
- std::string remove =
- cmStrCat("$(CMAKE_COMMAND) -P ",
- this->ConvertToOutputFormat(
- this->MaybeConvertToRelativePath(
- this->GetCurrentBinaryDirectory(), cleanfile),
- cmOutputConverter::SHELL));
+ std::string remove = cmStrCat(
+ "$(CMAKE_COMMAND) -P ",
+ this->ConvertToOutputFormat(this->MaybeRelativeToCurBinDir(cleanfile),
+ cmOutputConverter::SHELL));
commands.push_back(std::move(remove));
}
@@ -1146,7 +1137,6 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
}
const auto& rootLG = this->GetGlobalGenerator()->GetLocalGenerators().at(0);
- std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory();
std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory();
std::string cleanfile =
cmStrCat(currentBinaryDir, "/CMakeFiles/cmake_directory_clean.cmake");
@@ -1159,19 +1149,18 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
}
fout << "file(REMOVE_RECURSE\n";
for (std::string const& cfl : cleanFiles) {
- std::string fc = rootLG->MaybeConvertToRelativePath(
- binaryDir, cmSystemTools::CollapseFullPath(cfl, currentBinaryDir));
+ std::string fc = rootLG->MaybeRelativeToCurBinDir(
+ cmSystemTools::CollapseFullPath(cfl, currentBinaryDir));
fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n";
}
fout << ")\n";
}
// Create command
{
- std::string remove =
- cmStrCat("$(CMAKE_COMMAND) -P ",
- this->ConvertToOutputFormat(
- rootLG->MaybeConvertToRelativePath(binaryDir, cleanfile),
- cmOutputConverter::SHELL));
+ std::string remove = cmStrCat(
+ "$(CMAKE_COMMAND) -P ",
+ this->ConvertToOutputFormat(rootLG->MaybeRelativeToCurBinDir(cleanfile),
+ cmOutputConverter::SHELL));
commands.push_back(std::move(remove));
}
}
@@ -1521,13 +1510,11 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(
// Setup relative path top directories.
if (cmProp relativePathTopSource =
mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE")) {
- this->StateSnapshot.GetDirectory().SetRelativePathTopSource(
- relativePathTopSource->c_str());
+ this->SetRelativePathTopSource(*relativePathTopSource);
}
if (cmProp relativePathTopBinary =
mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY")) {
- this->StateSnapshot.GetDirectory().SetRelativePathTopBinary(
- relativePathTopBinary->c_str());
+ this->SetRelativePathTopBinary(*relativePathTopBinary);
}
} else {
cmSystemTools::Error("Directory Information file not found");
@@ -1563,7 +1550,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(
std::unique_ptr<cmDepends> scanner;
if (lang == "C" || lang == "CXX" || lang == "RC" || lang == "ASM" ||
lang == "OBJC" || lang == "OBJCXX" || lang == "CUDA" ||
- lang == "ISPC") {
+ lang == "HIP" || lang == "ISPC") {
// TODO: Handle RC (resource files) dependencies correctly.
scanner = cm::make_unique<cmDependsC>(this, targetDir, lang, &validDeps);
}
@@ -1964,8 +1951,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir));
}
for (std::string const& include : includes) {
- cmakefileStream << " \""
- << this->MaybeConvertToRelativePath(binaryDir, include)
+ cmakefileStream << " \"" << this->MaybeRelativeToTopBinDir(include)
<< "\"\n";
}
cmakefileStream << " )\n";
@@ -2004,12 +1990,9 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
for (auto const& compilerPair : compilerPairs) {
for (auto const& src : compilerPair.second) {
cmakefileStream << R"( "" ")"
- << this->MaybeConvertToRelativePath(
- this->GetBinaryDirectory(), compilerPair.first)
+ << this->MaybeRelativeToTopBinDir(compilerPair.first)
<< R"(" "custom" ")"
- << this->MaybeConvertToRelativePath(
- this->GetBinaryDirectory(), src)
- << "\"\n";
+ << this->MaybeRelativeToTopBinDir(src) << "\"\n";
}
}
} else {
@@ -2018,11 +2001,9 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
for (auto const& compilerPair : compilerPairs) {
for (auto const& src : compilerPair.second) {
cmakefileStream << " \"" << src << "\" \""
- << this->MaybeConvertToRelativePath(
- this->GetBinaryDirectory(), compilerPair.first)
+ << this->MaybeRelativeToTopBinDir(compilerPair.first)
<< "\" \"" << depFormat << "\" \""
- << this->MaybeConvertToRelativePath(
- this->GetBinaryDirectory(), compilerPair.first)
+ << this->MaybeRelativeToTopBinDir(compilerPair.first)
<< ".d\"\n";
}
}
@@ -2066,8 +2047,7 @@ std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall(
// Add the target.
if (!tgt.empty()) {
// The make target is always relative to the top of the build tree.
- std::string tgt2 =
- this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), tgt);
+ std::string tgt2 = this->MaybeRelativeToTopBinDir(tgt);
// The target may have been written with windows paths.
cmSystemTools::ConvertToOutputSlashes(tgt2);
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index a3940ead6..151470b4e 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -784,8 +784,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
cmProp target_mod_dir = target->GetProperty("Fortran_MODULE_DIRECTORY");
std::string modDir;
if (target_mod_dir) {
- modDir = this->MaybeConvertToRelativePath(
- this->GetCurrentBinaryDirectory(), *target_mod_dir);
+ modDir = this->MaybeRelativeToCurBinDir(*target_mod_dir);
} else {
modDir = ".";
}
@@ -1214,7 +1213,7 @@ void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool(
cmProp additionalFiles =
target->GetProperty("DEPLOYMENT_ADDITIONAL_FILES");
- if (dir == nullptr && additionalFiles == nullptr) {
+ if (!dir && !additionalFiles) {
return;
}
@@ -1228,7 +1227,7 @@ void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool(
<< GetEscapedPropertyIfValueNotNULL(additionalFiles->c_str())
<< "\"/>\n";
- if (dir != nullptr) {
+ if (dir) {
std::string const exe = *dir + "\\" + target->GetFullName(config);
fout << "\t\t\t<DebuggerTool\n"
@@ -1254,11 +1253,9 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries(
std::ostream& fout, ItemVector const& libs)
{
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
- std::string currentBinDir = lg->GetCurrentBinaryDirectory();
for (auto const& lib : libs) {
- if (lib.IsPath) {
- std::string rel =
- lg->MaybeConvertToRelativePath(currentBinDir, lib.Value.Value);
+ if (lib.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
+ std::string rel = lg->MaybeRelativeToCurBinDir(lib.Value.Value);
fout << lg->ConvertToXMLOutputPath(rel) << " ";
} else if (!lib.Target ||
lib.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
@@ -1274,7 +1271,6 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects(
// VS < 8 does not support per-config source locations so we
// list object library content on the link line instead.
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
- std::string currentBinDir = lg->GetCurrentBinaryDirectory();
std::vector<cmSourceFile const*> objs;
gt->GetExternalObjects(objs, configName);
@@ -1283,7 +1279,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects(
for (cmSourceFile const* obj : objs) {
if (!obj->GetObjectLibrary().empty()) {
std::string const& objFile = obj->GetFullPath();
- std::string rel = lg->MaybeConvertToRelativePath(currentBinDir, objFile);
+ std::string rel = lg->MaybeRelativeToCurBinDir(objFile);
fout << sep << lg->ConvertToXMLOutputPath(rel);
sep = " ";
}
@@ -1294,7 +1290,6 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
std::ostream& fout, std::vector<std::string> const& dirs)
{
const char* comma = "";
- std::string currentBinDir = this->GetCurrentBinaryDirectory();
for (std::string dir : dirs) {
// Remove any trailing slash and skip empty paths.
if (dir.back() == '/') {
@@ -1306,7 +1301,7 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
// Switch to a relative path specification if it is shorter.
if (cmSystemTools::FileIsFullPath(dir)) {
- std::string rel = this->MaybeConvertToRelativePath(currentBinDir, dir);
+ std::string rel = this->MaybeRelativeToCurBinDir(dir);
if (rel.size() < dir.size()) {
dir = rel;
}
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 6d6ed9f40..002f484bc 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -207,10 +207,8 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
}
if (workingDirectory.empty()) {
- script +=
- this->ConvertToOutputFormat(this->MaybeConvertToRelativePath(
- this->GetCurrentBinaryDirectory(), cmd),
- cmOutputConverter::SHELL);
+ script += this->ConvertToOutputFormat(
+ this->MaybeRelativeToCurBinDir(cmd), cmOutputConverter::SHELL);
} else {
script += this->ConvertToOutputFormat(cmd.c_str(), SHELL);
}
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index dd254063c..c970abe8a 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -800,7 +800,7 @@ void cmMakefile::RunListFile(cmListFile const& listFile,
for (size_t i = 0; i < defer->Commands.size(); ++i) {
DeferCommand& d = defer->Commands[i];
if (d.Id.empty()) {
- // Cancelled.
+ // Canceled.
continue;
}
// Mark as executed.
@@ -1222,7 +1222,7 @@ void cmMakefile::AddCustomCommandOldStyle(
// Each output must get its own copy of this rule.
cmsys::RegularExpression sourceFiles(
- "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|mpp|cu|m|mm|"
+ "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|mpp|ixx|cppm|cu|m|mm|"
"rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
"hm|hpp|hxx|in|txx|inl)$");
@@ -1962,8 +1962,27 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value,
}
}
this->GetCMakeInstance()->AddCacheEntry(name, value, doc, type);
- // if there was a definition then remove it
- this->StateSnapshot.RemoveDefinition(name);
+ switch (this->GetPolicyStatus(cmPolicies::CMP0126)) {
+ case cmPolicies::WARN:
+ if (this->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0126") &&
+ this->IsNormalDefinitionSet(name)) {
+ this->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0126),
+ "\nFor compatibility with older versions of CMake, normal "
+ "variable \"",
+ name, "\" will be removed from the current scope."));
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // if there was a definition then remove it
+ this->StateSnapshot.RemoveDefinition(name);
+ break;
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ break;
+ }
}
void cmMakefile::MarkVariableAsUsed(const std::string& var)
@@ -2479,7 +2498,7 @@ const std::string& cmMakefile::GetRequiredDefinition(
const std::string& name) const
{
static std::string const empty;
- const std::string* def = this->GetDefinition(name);
+ cmProp def = this->GetDefinition(name);
if (!def) {
cmSystemTools::Error("Error required internal CMake variable not "
"set, cmake may not be built correctly.\n"
@@ -2507,6 +2526,20 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const
return def != nullptr;
}
+bool cmMakefile::IsNormalDefinitionSet(const std::string& name) const
+{
+ cmProp def = this->StateSnapshot.GetDefinition(name);
+#ifndef CMAKE_BOOTSTRAP
+ if (cmVariableWatch* vv = this->GetVariableWatch()) {
+ if (!def) {
+ vv->VariableAccessed(
+ name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, nullptr, this);
+ }
+ }
+#endif
+ return def != nullptr;
+}
+
cmProp cmMakefile::GetDefinition(const std::string& name) const
{
cmProp def = this->StateSnapshot.GetDefinition(name);
@@ -2539,7 +2572,7 @@ cmProp cmMakefile::GetDefinition(const std::string& name) const
const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const
{
static std::string const empty;
- const std::string* def = this->GetDefinition(name);
+ cmProp def = this->GetDefinition(name);
if (!def) {
return empty;
}
@@ -3053,7 +3086,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew(
if (filename && variable == lineVar) {
varresult = std::to_string(line);
} else {
- const std::string* def = this->GetDefinition(variable);
+ cmProp def = this->GetDefinition(variable);
if (def) {
varresult = *def;
} else if (!this->SuppressSideEffects) {
@@ -3438,7 +3471,8 @@ void cmMakefile::CreateGeneratedOutputs(
void cmMakefile::AddTargetObject(std::string const& tgtName,
std::string const& objFile)
{
- cmSourceFile* sf = this->GetOrCreateSource(objFile, true);
+ cmSourceFile* sf =
+ this->GetOrCreateSource(objFile, true, cmSourceFileLocationKind::Known);
sf->SetObjectLibrary(tgtName);
sf->SetProperty("EXTERNAL_OBJECT", "1");
#if !defined(CMAKE_BOOTSTRAP)
@@ -4117,6 +4151,7 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name,
// Add to the set of available imported targets.
this->ImportedTargets[name] = target.get();
this->GetGlobalGenerator()->IndexTarget(target.get());
+ this->GetStateSnapshot().GetDirectory().AddImportedTargetName(name);
// Transfer ownership to this cmMakefile object.
this->ImportedTargetsOwned.push_back(std::move(target));
@@ -4393,7 +4428,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
// Deprecate old policies, especially those that require a lot
// of code to maintain the old behavior.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0075 &&
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0081 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 71d765c71..77e9c7405 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -486,6 +486,7 @@ public:
const std::string& GetSafeDefinition(const std::string&) const;
const std::string& GetRequiredDefinition(const std::string& name) const;
bool IsDefinitionSet(const std::string&) const;
+ bool IsNormalDefinitionSet(const std::string&) const;
bool GetDefExpandList(const std::string& name, std::vector<std::string>& out,
bool emptyArgs = false) const;
/**
@@ -992,7 +993,7 @@ private:
struct DeferCommand
{
- // Id is empty for an already-executed or cancelled operation.
+ // Id is empty for an already-executed or canceled operation.
std::string Id;
std::string FilePath;
cmListFileFunction Command;
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 1750e37ad..3a2744e3f 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -104,13 +104,11 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
cmLocalUnixMakefileGenerator3::EchoProgress progress;
this->MakeEchoProgress(progress);
// Add the link message.
- std::string buildEcho =
- cmStrCat("Linking CUDA device code ",
- this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
- this->DeviceLinkObject),
- cmOutputConverter::SHELL));
+ std::string buildEcho = cmStrCat(
+ "Linking CUDA device code ",
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(this->DeviceLinkObject),
+ cmOutputConverter::SHELL));
this->LocalGenerator->AppendEcho(
commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
}
@@ -152,8 +150,8 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
// Construct a list of files associated with this executable that
// may need to be cleaned.
std::vector<std::string> exeCleanFiles;
- exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput));
+ exeCleanFiles.push_back(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput));
// Determine whether a link script will be used.
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
@@ -203,17 +201,14 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
objectDir = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
cmOutputConverter::SHELL);
cmOutputConverter::OutputFormat output = (useWatcomQuote)
? cmOutputConverter::WATCOMQUOTE
: cmOutputConverter::SHELL;
std::string target = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput),
- output);
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput), output);
std::string targetFullPathCompilePDB =
this->ComputeTargetCompilePDB(this->GetConfigName());
@@ -330,18 +325,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
targetFullPathPDB, cmOutputConverter::SHELL);
// Convert to the output path to use in constructing commands.
std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath),
cmOutputConverter::SHELL);
std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
cmOutputConverter::SHELL);
std::string targetOutPathImport =
this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
- targetFullPathImport),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport),
cmOutputConverter::SHELL);
// Get the language to use for linking this executable.
@@ -384,11 +375,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
if (this->GeneratorTarget->IsWin32Executable(
this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) {
this->LocalGenerator->AppendFlags(
- linkFlags, this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"));
+ linkFlags,
+ this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE")));
} else {
this->LocalGenerator->AppendFlags(
linkFlags,
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE"));
+ this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_CONSOLE_EXE")));
}
// Add symbol export flags if necessary.
@@ -433,36 +427,34 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Construct a list of files associated with this executable that
// may need to be cleaned.
std::vector<std::string> exeCleanFiles;
- exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
+ exeCleanFiles.push_back(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath));
#ifdef _WIN32
// There may be a manifest file for this target. Add it to the
// clean set just in case.
- exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
+ exeCleanFiles.push_back(this->LocalGenerator->MaybeRelativeToCurBinDir(
targetFullPath + ".manifest"));
#endif
if (this->TargetNames.Real != this->TargetNames.Output) {
- exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
+ exeCleanFiles.push_back(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal));
}
if (!this->TargetNames.ImportLibrary.empty()) {
- exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
- targetFullPathImport));
+ exeCleanFiles.push_back(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport));
std::string implib;
if (this->GeneratorTarget->GetImplibGNUtoMS(
this->GetConfigName(), targetFullPathImport, implib)) {
- exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
+ exeCleanFiles.push_back(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(implib));
}
}
// List the PDB for cleaning only when the whole target is
// cleaned. We do not want to delete the .pdb file just before
// linking the target.
- this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB));
+ this->CleanFiles.insert(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathPDB));
// Add the pre-build and pre-link rules building but not when relinking.
if (!relink) {
@@ -526,8 +518,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
if (!this->DeviceLinkObject.empty()) {
buildObjs += " " +
this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(
this->DeviceLinkObject),
cmOutputConverter::SHELL);
}
@@ -546,16 +537,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
objectDir = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
cmOutputConverter::SHELL);
vars.ObjectDir = objectDir.c_str();
cmOutputConverter::OutputFormat output = (useWatcomQuote)
? cmOutputConverter::WATCOMQUOTE
: cmOutputConverter::SHELL;
std::string target = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
output);
vars.Target = target.c_str();
vars.TargetPDB = targetOutPathPDB.c_str();
@@ -582,6 +571,12 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
vars.LinkFlags = linkFlags.c_str();
vars.Manifests = manifests.c_str();
+ std::string linkerLauncher =
+ this->GetLinkerLauncher(this->GetConfigName());
+ if (cmNonempty(linkerLauncher)) {
+ vars.Launcher = linkerLauncher.c_str();
+ }
+
if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
std::string cmakeCommand =
cmStrCat(this->LocalGenerator->ConvertToOutputFormat(
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index ce64e2cfa..d0e3837dd 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -250,13 +250,11 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
cmLocalUnixMakefileGenerator3::EchoProgress progress;
this->MakeEchoProgress(progress);
// Add the link message.
- std::string buildEcho =
- cmStrCat("Linking CUDA device code ",
- this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
- this->DeviceLinkObject),
- cmOutputConverter::SHELL));
+ std::string buildEcho = cmStrCat(
+ "Linking CUDA device code ",
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(this->DeviceLinkObject),
+ cmOutputConverter::SHELL));
this->LocalGenerator->AppendEcho(
commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
}
@@ -293,8 +291,8 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
// Clean files associated with this library.
std::set<std::string> libCleanFiles;
- libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput));
+ libCleanFiles.insert(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput));
// Determine whether a link script will be used.
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
@@ -342,14 +340,11 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
objectDir = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
cmOutputConverter::SHELL);
std::string target = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput),
- output);
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput), output);
std::string targetFullPathCompilePDB =
this->ComputeTargetCompilePDB(this->GetConfigName());
@@ -519,22 +514,17 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
targetFullPathPDB, cmOutputConverter::SHELL);
std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath),
cmOutputConverter::SHELL);
std::string targetOutPathSO = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathSO),
cmOutputConverter::SHELL);
std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
cmOutputConverter::SHELL);
std::string targetOutPathImport =
this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
- targetFullPathImport),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport),
cmOutputConverter::SHELL);
this->NumberOfProgressActions++;
@@ -567,8 +557,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Clean files associated with this library.
std::set<std::string> libCleanFiles;
- libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
+ libCleanFiles.insert(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal));
std::vector<std::string> commands1;
// Add a command to remove any existing files for this library.
@@ -584,38 +574,36 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
}
if (this->TargetNames.Output != this->TargetNames.Real) {
- libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
+ libCleanFiles.insert(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath));
}
if (this->TargetNames.SharedObject != this->TargetNames.Real &&
this->TargetNames.SharedObject != this->TargetNames.Output) {
- libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO));
+ libCleanFiles.insert(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathSO));
}
if (!this->TargetNames.ImportLibrary.empty()) {
- libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
- targetFullPathImport));
+ libCleanFiles.insert(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport));
std::string implib;
if (this->GeneratorTarget->GetImplibGNUtoMS(
this->GetConfigName(), targetFullPathImport, implib)) {
- libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
+ libCleanFiles.insert(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(implib));
}
}
// List the PDB for cleaning only when the whole target is
// cleaned. We do not want to delete the .pdb file just before
// linking the target.
- this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB));
+ this->CleanFiles.insert(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathPDB));
#ifdef _WIN32
// There may be a manifest file for this target. Add it to the
// clean set just in case.
if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) {
- libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
+ libCleanFiles.insert(this->LocalGenerator->MaybeRelativeToCurBinDir(
targetFullPath + ".manifest"));
}
#endif
@@ -723,8 +711,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
if (!this->DeviceLinkObject.empty()) {
buildObjs += " " +
this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(
this->DeviceLinkObject),
cmOutputConverter::SHELL);
}
@@ -765,8 +752,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
objectDir = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
cmOutputConverter::SHELL);
vars.ObjectDir = objectDir.c_str();
@@ -774,15 +760,17 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
? cmOutputConverter::WATCOMQUOTE
: cmOutputConverter::SHELL;
std::string target = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
output);
vars.Target = target.c_str();
vars.LinkLibraries = linkLibs.c_str();
vars.ObjectsQuoted = buildObjs.c_str();
+ std::string targetOutSOName;
if (this->GeneratorTarget->HasSOName(this->GetConfigName())) {
vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
- vars.TargetSOName = this->TargetNames.SharedObject.c_str();
+ targetOutSOName = this->LocalGenerator->ConvertToOutputFormat(
+ this->TargetNames.SharedObject.c_str(), cmOutputConverter::SHELL);
+ vars.TargetSOName = targetOutSOName.c_str();
}
vars.LinkFlags = linkFlags.c_str();
@@ -816,6 +804,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
vars.LanguageCompileFlags = langFlags.c_str();
+ std::string linkerLauncher =
+ this->GetLinkerLauncher(this->GetConfigName());
+ if (cmNonempty(linkerLauncher)) {
+ vars.Launcher = linkerLauncher.c_str();
+ }
+
std::string launcher;
cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
"RULE_LAUNCH_LINK");
@@ -836,8 +830,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// only occur on archives which have CUDA_RESOLVE_DEVICE_SYMBOLS enabled
if (!this->DeviceLinkObject.empty()) {
object_strings.push_back(this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(
this->DeviceLinkObject),
cmOutputConverter::SHELL));
}
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 5f7f3dc5b..6d8376c67 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -218,15 +218,12 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
}
}
- std::string currentBinDir =
- this->LocalGenerator->GetCurrentBinaryDirectory();
-
// Look for ISPC extra object files generated by this target
auto ispcAdditionalObjs =
this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
for (std::string const& ispcObj : ispcAdditionalObjs) {
- this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
- currentBinDir, ispcObj));
+ this->CleanFiles.insert(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(ispcObj));
}
// add custom commands to the clean rules?
@@ -251,14 +248,12 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
const std::vector<std::string>& outputs = ccg.GetOutputs();
for (std::string const& output : outputs) {
this->CleanFiles.insert(
- this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
- output));
+ this->LocalGenerator->MaybeRelativeToCurBinDir(output));
}
const std::vector<std::string>& byproducts = ccg.GetByproducts();
for (std::string const& byproduct : byproducts) {
this->CleanFiles.insert(
- this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
- byproduct));
+ this->LocalGenerator->MaybeRelativeToCurBinDir(byproduct));
}
}
}
@@ -279,8 +274,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
const std::vector<std::string>& byproducts = beg.GetByproducts();
for (std::string const& byproduct : byproducts) {
this->CleanFiles.insert(
- this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
- byproduct));
+ this->LocalGenerator->MaybeRelativeToCurBinDir(byproduct));
}
}
}
@@ -327,8 +321,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
<< "# Include any dependencies generated for this target.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(), dependFileNameFull))
+ this->LocalGenerator->MaybeRelativeToTopBinDir(dependFileNameFull))
<< "\n";
std::string depsUseCompiler = "CMAKE_DEPENDS_USE_COMPILER";
@@ -336,14 +329,14 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
this->Makefile->IsOn(depsUseCompiler)) {
std::string compilerDependFile =
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
- *this->BuildFileStream
- << "# Include any dependencies generated by the "
- "compiler for this target.\n"
- << this->GlobalGenerator->IncludeDirective << " " << root
- << cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(), compilerDependFile))
- << "\n\n";
+ *this->BuildFileStream << "# Include any dependencies generated by the "
+ "compiler for this target.\n"
+ << this->GlobalGenerator->IncludeDirective << " "
+ << root
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator->MaybeRelativeToTopBinDir(
+ compilerDependFile))
+ << "\n\n";
// Write an empty dependency file.
cmGeneratedFileStream depFileStream(
@@ -399,8 +392,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
<< "# Include the progress variables for this target.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(),
+ this->LocalGenerator->MaybeRelativeToTopBinDir(
this->ProgressFileNameFull))
<< "\n\n";
}
@@ -423,8 +415,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
<< "# Include the compile flags for this target's objects.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(), this->FlagFileNameFull))
+ this->LocalGenerator->MaybeRelativeToTopBinDir(
+ this->FlagFileNameFull))
<< "\n\n";
}
@@ -491,10 +483,8 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
std::string output =
cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input));
this->Generator->CleanFiles.insert(
- this->Generator->LocalGenerator->MaybeConvertToRelativePath(
- this->Generator->LocalGenerator->GetCurrentBinaryDirectory(), output));
- output = this->Generator->LocalGenerator->MaybeConvertToRelativePath(
- this->Generator->LocalGenerator->GetBinaryDirectory(), output);
+ this->Generator->LocalGenerator->MaybeRelativeToCurBinDir(output));
+ output = this->Generator->LocalGenerator->MaybeRelativeToTopBinDir(output);
// Create a rule to copy the content into the bundle.
std::vector<std::string> depends;
@@ -663,7 +653,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
cmProp ispcSuffixProp =
this->GeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX");
- assert(ispcSuffixProp != nullptr);
+ assert(ispcSuffixProp);
std::string directory = this->GeneratorTarget->GetObjectDirectory(config);
if (cmProp prop =
@@ -797,15 +787,12 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
}
targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
cmOutputConverter::SHELL);
targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
targetFullPathPDB, cmOutputConverter::SHELL);
targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
- targetFullPathCompilePDB),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathCompilePDB),
cmOutputConverter::SHELL);
if (this->LocalGenerator->IsMinGWMake() &&
@@ -834,14 +821,12 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
vars.Object = shellObj.c_str();
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
objectDir = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
cmOutputConverter::SHELL);
vars.ObjectDir = objectDir.c_str();
std::string objectFileDir = cmSystemTools::GetFilenamePath(obj);
objectFileDir = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), objectFileDir),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(objectFileDir),
cmOutputConverter::SHELL);
vars.ObjectFileDir = objectFileDir.c_str();
vars.Flags = flags.c_str();
@@ -854,7 +839,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
vars.Defines = definesString.c_str();
std::string includesString = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, lang, true, false, config);
+ includes, this->GeneratorTarget, lang, config);
this->LocalGenerator->AppendFlags(includesString,
"$(" + lang + "_INCLUDES)");
vars.Includes = includesString.c_str();
@@ -865,8 +850,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
if (compilerGenerateDeps) {
dependencyTarget = this->LocalGenerator->EscapeForShell(
this->LocalGenerator->ConvertToMakefilePath(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(), relativeObj)));
+ this->LocalGenerator->MaybeRelativeToTopBinDir(relativeObj)));
vars.DependencyTarget = dependencyTarget.c_str();
auto depFile = cmStrCat(obj, ".d");
@@ -875,8 +859,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
vars.DependencyFile = shellDependencyFile.c_str();
this->CleanFiles.insert(depFile);
- dependencyTimestamp = this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(),
+ dependencyTimestamp = this->LocalGenerator->MaybeRelativeToTopBinDir(
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"));
}
@@ -962,7 +945,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
std::string compilerLauncher;
if (!compileCommands.empty() &&
(lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
- lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) {
+ lang == "HIP" || lang == "ISPC" || lang == "OBJC" ||
+ lang == "OBJCXX")) {
std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
if (cmNonempty(clauncher)) {
@@ -1305,12 +1289,11 @@ bool cmMakefileTargetGenerator::WriteMakeRule(
// For multiple outputs, make the extra ones depend on the first one.
std::vector<std::string> const output_depends(1, outputs[0]);
- std::string binDir = this->LocalGenerator->GetBinaryDirectory();
for (std::string const& output : cmMakeRange(outputs).advance(1)) {
// Touch the extra output so "make" knows that it was updated,
// but only if the output was actually created.
std::string const out = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(binDir, output),
+ this->LocalGenerator->MaybeRelativeToTopBinDir(output),
cmOutputConverter::SHELL);
std::vector<std::string> output_commands;
@@ -1518,14 +1501,12 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
const std::string objectDir = this->GeneratorTarget->ObjectDirectory;
const std::string relObjectDir =
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir);
+ this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir);
// Construct a list of files associated with this executable that
// may need to be cleaned.
std::vector<std::string> cleanFiles;
- cleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), output));
+ cleanFiles.push_back(this->LocalGenerator->MaybeRelativeToCurBinDir(output));
std::string profiles;
std::vector<std::string> fatbinaryDepends;
@@ -1550,8 +1531,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
// generate it only on the first invocation to reduce overhead.
if (fatbinaryDepends.size() == 1) {
std::string registerFileRel =
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), registerFile);
+ this->LocalGenerator->MaybeRelativeToCurBinDir(registerFile);
registerFileCmd =
cmStrCat(" --register-link-binaries=", registerFileRel);
cleanFiles.push_back(registerFileRel);
@@ -1575,8 +1555,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
const std::string fatbinaryOutput =
cmStrCat(objectDir, "cmake_cuda_fatbin.h");
const std::string fatbinaryOutputRel =
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), fatbinaryOutput);
+ this->LocalGenerator->MaybeRelativeToCurBinDir(fatbinaryOutput);
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
fatbinaryOutputRel, fatbinaryDepends,
@@ -1643,8 +1622,7 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
if (!ccg.GetCC().GetDepfile().empty()) {
// Add dependency over timestamp file for dependencies management
auto dependTimestamp = cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(),
+ this->LocalGenerator->MaybeRelativeToTopBinDir(
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")));
depends.push_back(dependTimestamp);
@@ -1746,11 +1724,8 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
<< this->GeneratorTarget->GetName() << "\n"
<< variableNameExternal << " =";
/* clang-format on */
- std::string currentBinDir =
- this->LocalGenerator->GetCurrentBinaryDirectory();
for (std::string const& obj : this->ExternalObjects) {
- object =
- this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, obj);
+ object = this->LocalGenerator->MaybeRelativeToCurBinDir(obj);
*this->BuildFileStream << " " << lineContinue;
*this->BuildFileStream
<< cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
@@ -1778,7 +1753,8 @@ public:
{
// Construct the name of the next object.
this->NextObject = this->OutputConverter->ConvertToOutputFormat(
- this->MaybeConvertToRelativePath(obj), cmOutputConverter::RESPONSE);
+ this->OutputConverter->MaybeRelativeToCurBinDir(obj),
+ cmOutputConverter::RESPONSE);
// Roll over to next string if the limit will be exceeded.
if (this->LengthLimit != std::string::npos &&
@@ -1799,15 +1775,6 @@ public:
void Done() { this->Strings.push_back(this->CurrentString); }
private:
- std::string MaybeConvertToRelativePath(std::string const& obj)
- {
- if (!this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), obj)) {
- return obj;
- }
- return cmSystemTools::ForceToRelativePath(
- this->StateDir.GetCurrentBinary(), obj);
- }
-
std::vector<std::string>& Strings;
cmOutputConverter* OutputConverter;
cmStateDirectory StateDir;
@@ -1850,8 +1817,8 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(
this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
std::string buildTargetRuleName =
cmStrCat(dir, relink ? "/preinstall" : "/build");
- buildTargetRuleName = this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(), buildTargetRuleName);
+ buildTargetRuleName =
+ this->LocalGenerator->MaybeRelativeToTopBinDir(buildTargetRuleName);
// Build the list of target outputs to drive.
std::vector<std::string> depends;
@@ -1988,13 +1955,12 @@ void cmMakefileTargetGenerator::CreateLinkScript(
}
// Create the makefile command to invoke the link script.
- std::string link_command = cmStrCat(
- "$(CMAKE_COMMAND) -E cmake_link_script ",
- this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName),
- cmOutputConverter::SHELL),
- " --verbose=$(VERBOSE)");
+ std::string link_command =
+ cmStrCat("$(CMAKE_COMMAND) -E cmake_link_script ",
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeRelativeToCurBinDir(linkScriptName),
+ cmOutputConverter::SHELL),
+ " --verbose=$(VERBOSE)");
makefile_commands.push_back(std::move(link_command));
makefile_depends.push_back(std::move(linkScriptName));
}
@@ -2061,7 +2027,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
// Create the response file.
std::string responseFileNameFull =
cmStrCat(this->TargetBuildDirectoryFull, '/', name);
- cmGeneratedFileStream responseStream(responseFileNameFull);
+ cmGeneratedFileStream responseStream(
+ responseFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
responseStream.SetCopyIfDifferent(true);
responseStream << options << "\n";
@@ -2198,8 +2165,8 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
lang, this->GetConfigName());
std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, lang, false, useResponseFile,
- this->GetConfigName());
+ includes, this->GeneratorTarget, lang, this->GetConfigName(),
+ useResponseFile);
if (includeFlags.empty()) {
return;
}
@@ -2235,14 +2202,12 @@ void cmMakefileTargetGenerator::GenDefFile(
this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL),
" -E __create_def ",
this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(mdi->DefFile),
cmOutputConverter::SHELL),
' ');
std::string objlist_file = mdi->DefFile + ".objs";
cmd += this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
+ this->LocalGenerator->MaybeRelativeToCurBinDir(objlist_file),
cmOutputConverter::SHELL);
cmProp nm_executable = this->Makefile->GetDefinition("CMAKE_NM");
if (cmNonempty(nm_executable)) {
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
index a885b1716..7f854ee6e 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -48,8 +48,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
<< "# Include any custom commands dependencies for this target.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(), dependFile))
+ this->LocalGenerator->MaybeRelativeToTopBinDir(dependFile))
<< "\n\n";
if (!cmSystemTools::FileExists(dependFile)) {
// Write an empty dependency file.
@@ -78,8 +77,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
<< "# Include the progress variables for this target.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(),
+ this->LocalGenerator->MaybeRelativeToTopBinDir(
this->ProgressFileNameFull))
<< "\n\n";
}
diff --git a/Source/cmMessageMetadata.h b/Source/cmMessageMetadata.h
new file mode 100644
index 000000000..7b56faed7
--- /dev/null
+++ b/Source/cmMessageMetadata.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmsys/Terminal.h"
+
+struct cmMessageMetadata
+{
+ const char* title = nullptr;
+ int desiredColor = cmsysTerminal_Color_Normal;
+};
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index af83478a6..1cb638ac2 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -3,6 +3,7 @@
#include "cmMessenger.h"
#include "cmDocumentationFormatter.h"
+#include "cmMessageMetadata.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -12,6 +13,8 @@
#include <sstream>
+#include "cmsys/Terminal.h"
+
MessageType cmMessenger::ConvertMessageType(MessageType t) const
{
bool warningsAsErrors;
@@ -84,6 +87,21 @@ static bool printMessagePreamble(MessageType t, std::ostream& msg)
return true;
}
+static int getMessageColor(MessageType t)
+{
+ switch (t) {
+ case MessageType::INTERNAL_ERROR:
+ case MessageType::FATAL_ERROR:
+ case MessageType::AUTHOR_ERROR:
+ return cmsysTerminal_Color_ForegroundRed;
+ case MessageType::AUTHOR_WARNING:
+ case MessageType::WARNING:
+ return cmsysTerminal_Color_ForegroundYellow;
+ default:
+ return cmsysTerminal_Color_Normal;
+ }
+}
+
void printMessageText(std::ostream& msg, std::string const& text)
{
msg << ":\n";
@@ -120,12 +138,16 @@ void displayMessage(MessageType t, std::ostringstream& msg)
#endif
// Output the message.
+ cmMessageMetadata md;
+ md.desiredColor = getMessageColor(t);
if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
cmSystemTools::SetErrorOccured();
- cmSystemTools::Message(msg.str(), "Error");
+ md.title = "Error";
+ cmSystemTools::Message(msg.str(), md);
} else {
- cmSystemTools::Message(msg.str(), "Warning");
+ md.title = "Warning";
+ cmSystemTools::Message(msg.str(), md);
}
}
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 1597d2c19..5a4c6521d 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -368,7 +368,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
vars.CMTargetType = cmState::GetTargetTypeName(targetType).c_str();
std::string lang = this->TargetLinkLanguage(config);
- vars.Language = config.c_str();
+ vars.Language = lang.c_str();
vars.AIXExports = "$AIX_EXPORTS";
if (this->TargetLinkLanguage(config) == "Swift") {
@@ -456,6 +456,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
vars.LanguageCompileFlags = langFlags.c_str();
}
+ std::string linkerLauncher = this->GetLinkerLauncher(config);
+ if (cmNonempty(linkerLauncher)) {
+ vars.Launcher = linkerLauncher.c_str();
+ }
+
std::string launcher;
cmProp val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
@@ -875,7 +880,8 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement(
if (genTarget->HasSOName(config)) {
vars["SONAME_FLAG"] =
this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage(config));
- vars["SONAME"] = tgtNames.SharedObject;
+ vars["SONAME"] = localGen.ConvertToOutputFormat(tgtNames.SharedObject,
+ cmOutputConverter::SHELL);
if (genTarget->GetType() == cmStateEnums::SHARED_LIBRARY) {
std::string install_dir =
this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(config);
@@ -1072,7 +1078,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
for (const auto& source : sources) {
oss << " "
<< LocalGen->ConvertToOutputFormat(
- this->ConvertToNinjaPath(this->GetSourceFilePath(source)),
+ this->GetCompiledSourceNinjaPath(source),
cmOutputConverter::SHELL);
}
return oss.str();
@@ -1093,8 +1099,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
for (const auto& source : sources) {
linkBuild.Outputs.push_back(
this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)));
- linkBuild.ExplicitDeps.push_back(
- this->ConvertToNinjaPath(this->GetSourceFilePath(source)));
+ linkBuild.ExplicitDeps.emplace_back(
+ this->GetCompiledSourceNinjaPath(source));
}
linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]);
} else {
@@ -1150,16 +1156,15 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"],
config);
+ if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
+ vars["LINK_FLAGS"] += " -Wl,--no-as-needed";
+ }
vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]);
vars["MANIFESTS"] = this->GetManifests(config);
vars["AIX_EXPORTS"] = this->GetAIXExports(config);
vars["LINK_PATH"] = frameworkPath + linkPath;
- std::string lwyuFlags;
- if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- lwyuFlags = " -Wl,--no-as-needed";
- }
// Compute architecture specific link flags. Yes, these go into a different
// variable for executables, probably due to a mistake made when duplicating
@@ -1168,7 +1173,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
std::string t = vars["FLAGS"];
localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config),
config);
- t += lwyuFlags;
vars["FLAGS"] = t;
} else {
std::string t = vars["ARCH_FLAGS"];
@@ -1176,14 +1180,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
config);
vars["ARCH_FLAGS"] = t;
t.clear();
- t += lwyuFlags;
localGen.AddLanguageFlagsForLinking(
t, gt, this->TargetLinkLanguage(config), config);
vars["LANGUAGE_COMPILE_FLAGS"] = t;
}
if (gt->HasSOName(config)) {
vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage(config));
- vars["SONAME"] = tgtNames.SharedObject;
+ vars["SONAME"] = localGen.ConvertToOutputFormat(tgtNames.SharedObject,
+ cmOutputConverter::SHELL);
if (targetType == cmStateEnums::SHARED_LIBRARY) {
std::string install_dir = gt->GetInstallNameDirForBuildTree(config);
if (!install_dir.empty()) {
@@ -1193,7 +1197,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
}
}
- cmNinjaDeps byproducts;
+ cmGlobalNinjaGenerator::CCOutputs byproducts(this->GetGlobalGenerator());
if (!tgtNames.ImportLibrary.empty()) {
const std::string impLibPath = localGen.ConvertToOutputFormat(
@@ -1201,7 +1205,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
vars["TARGET_IMPLIB"] = impLibPath;
this->EnsureParentDirectoryExists(impLibPath);
if (gt->HasImportLibrary(config)) {
- byproducts.push_back(targetOutputImplib);
+ // Some linkers may update a binary without touching its import lib.
+ byproducts.ExplicitOuts.emplace_back(targetOutputImplib);
if (firstForConfig) {
globalGen->GetByproductsForCleanTarget(config).push_back(
targetOutputImplib);
@@ -1259,8 +1264,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
true, config);
localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
- std::transform(ccByproducts.begin(), ccByproducts.end(),
- std::back_inserter(byproducts), this->MapToNinjaPath());
+ byproducts.Add(ccByproducts);
std::transform(
ccByproducts.begin(), ccByproducts.end(),
std::back_inserter(globalGen->GetByproductsForCleanTarget()),
@@ -1380,12 +1384,13 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
}
// Ninja should restat after linking if and only if there are byproducts.
- vars["RESTAT"] = byproducts.empty() ? "" : "1";
+ vars["RESTAT"] = byproducts.ExplicitOuts.empty() ? "" : "1";
- for (std::string const& o : byproducts) {
- globalGen->SeenCustomCommandOutput(o);
- linkBuild.Outputs.push_back(o);
- }
+ linkBuild.Outputs.reserve(linkBuild.Outputs.size() +
+ byproducts.ExplicitOuts.size());
+ std::move(byproducts.ExplicitOuts.begin(), byproducts.ExplicitOuts.end(),
+ std::back_inserter(linkBuild.Outputs));
+ linkBuild.WorkDirOuts = std::move(byproducts.WorkDirOuts);
// Write the build statement for this target.
bool usedResponseFile = false;
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index b4838d667..609848b43 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -263,9 +263,10 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
language, config);
// Add include directory flags.
std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, language,
- language == "RC", // full include paths for RC needed by cmcldeps
- false, config);
+ includes, this->GeneratorTarget, language, config, false,
+ // full include paths for RC needed by cmcldeps
+ language == "RC" ? cmLocalGenerator::IncludePathStyle::Absolute
+ : cmLocalGenerator::IncludePathStyle::Default);
if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/');
}
@@ -324,7 +325,8 @@ std::string cmNinjaTargetGenerator::ComputeIncludes(
}
std::string includesString = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, language, true, false, config);
+ includes, this->GeneratorTarget, language, config, false,
+ cmLocalGenerator::IncludePathStyle::Absolute);
this->LocalGenerator->AppendFlags(includesString,
this->GetIncludes(language, config));
@@ -377,10 +379,11 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
return result;
}
-std::string cmNinjaTargetGenerator::GetSourceFilePath(
+std::string cmNinjaTargetGenerator::GetCompiledSourceNinjaPath(
cmSourceFile const* source) const
{
- return this->ConvertToNinjaPath(source->GetFullPath());
+ // Pass source files to the compiler by absolute path.
+ return this->ConvertToNinjaAbsPath(source->GetFullPath());
}
std::string cmNinjaTargetGenerator::GetObjectFilePath(
@@ -526,14 +529,14 @@ std::string GetScanCommand(const std::string& cmakeCmd, const std::string& tdi,
const std::string& ddiFile)
{
return cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi,
- " --lang=", lang, " --src=$in", " --pp=", ppFile,
+ " --lang=", lang, " --pp=", ppFile,
" --dep=$DEP_FILE --obj=$OBJ_FILE --ddi=", ddiFile);
}
// Helper function to create dependency scanning rule that may or may
// not perform explicit preprocessing too.
cmNinjaRule GetScanRule(
- const std::string& ruleName,
+ std::string const& ruleName, std::string const& ppFileName,
cmRulePlaceholderExpander::RuleVariables const& vars,
const std::string& responseFlag, const std::string& flags,
cmRulePlaceholderExpander* const rulePlaceholderExpander,
@@ -550,7 +553,7 @@ cmNinjaRule GetScanRule(
scanVars.CMTargetType = vars.CMTargetType;
scanVars.Language = vars.Language;
scanVars.Object = "$OBJ_FILE";
- scanVars.PreprocessedSource = "$out";
+ scanVars.PreprocessedSource = ppFileName.c_str();
scanVars.DynDepFile = "$DYNDEP_INTERMEDIATE_FILE";
scanVars.DependencyFile = rule.DepFile.c_str();
scanVars.DependencyTarget = "$out";
@@ -650,8 +653,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
{
std::vector<std::string> scanCommands;
std::string scanRuleName;
+ std::string ppFileName;
if (compilationPreprocesses) {
scanRuleName = this->LanguageScanRule(lang, config);
+ ppFileName = "$PREPROCESSED_OUTPUT_FILE";
std::string const& scanCommand = mf->GetRequiredDefinition(
cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_SCANDEP_SOURCE"));
cmExpandList(scanCommand, scanCommands);
@@ -660,6 +665,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
}
} else {
scanRuleName = this->LanguagePreprocessAndScanRule(lang, config);
+ ppFileName = "$out";
std::string const& ppCommmand = mf->GetRequiredDefinition(
cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE"));
cmExpandList(ppCommmand, scanCommands);
@@ -670,9 +676,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
"$DYNDEP_INTERMEDIATE_FILE"));
}
- auto scanRule = GetScanRule(
- scanRuleName, vars, responseFlag, flags, rulePlaceholderExpander.get(),
- this->GetLocalGenerator(), std::move(scanCommands), config);
+ auto scanRule =
+ GetScanRule(scanRuleName, ppFileName, vars, responseFlag, flags,
+ rulePlaceholderExpander.get(), this->GetLocalGenerator(),
+ std::move(scanCommands), config);
scanRule.Comment =
cmStrCat("Rule for generating ", lang, " dependencies.");
@@ -701,7 +708,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
GetScanCommand(cmakeCmd, tdi, lang, "$in", "$out"));
auto scanRule = GetScanRule(
- scanRuleName, vars, "", flags, rulePlaceholderExpander.get(),
+ scanRuleName, "", vars, "", flags, rulePlaceholderExpander.get(),
this->GetLocalGenerator(), std::move(scanCommands), config);
// Write the rule for generating dependencies for the given language.
@@ -830,7 +837,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
std::string compilerLauncher;
if (!compileCmds.empty() &&
(lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
- lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) {
+ lang == "HIP" || lang == "ISPC" || lang == "OBJC" ||
+ lang == "OBJCXX")) {
std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
if (cmNonempty(clauncher)) {
@@ -985,7 +993,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
this->GeneratorTarget->GetExternalObjects(externalObjects, config);
for (cmSourceFile const* sf : externalObjects) {
auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir(
- this->GetSourceFilePath(sf), config);
+ this->ConvertToNinjaPath(sf->GetFullPath()), config);
if (!cmSystemTools::StringEndsWith(objectFileName,
cmToCStr(pchExtension))) {
this->Configs[config].Objects.push_back(objectFileName);
@@ -1114,11 +1122,7 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName,
{
cmNinjaBuild scanBuild(ruleName);
- if (!ppFileName.empty()) {
- scanBuild.RspFile = cmStrCat(ppFileName, ".rsp");
- } else {
- scanBuild.RspFile = "$out.rsp";
- }
+ scanBuild.RspFile = "$out.rsp";
if (compilePP) {
// Move compilation dependencies to the scan/preprocessing build statement.
@@ -1162,11 +1166,12 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName,
scanBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
// Outputs of the scan/preprocessor build statement.
- if (!ppFileName.empty()) {
+ if (compilePP) {
scanBuild.Outputs.push_back(ppFileName);
scanBuild.ImplicitOuts.push_back(ddiFile);
} else {
scanBuild.Outputs.push_back(ddiFile);
+ scanBuild.Variables["PREPROCESSED_OUTPUT_FILE"] = ppFileName;
}
// Scanning always uses a depfile for preprocessor dependencies.
@@ -1197,8 +1202,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
const std::string& fileConfig, bool firstForConfig)
{
std::string const language = source->GetLanguage();
- std::string const sourceFileName =
- language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source);
+ std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(source);
std::string const objectDir = this->ConvertToNinjaPath(
cmStrCat(this->GeneratorTarget->GetSupportDirectory(),
this->GetGlobalGenerator()->ConfigDirectory(config)));
@@ -1249,7 +1253,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
this->ExportObjectCompileCommand(
- language, sourceFileName, objectDir, objectFileName, objectFileDir,
+ language, sourceFilePath, objectDir, objectFileName, objectFileDir,
vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
objBuild.Outputs.push_back(objectFileName);
@@ -1263,7 +1267,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
}
- objBuild.ExplicitDeps.push_back(sourceFileName);
+ objBuild.ExplicitDeps.push_back(sourceFilePath);
// Add precompile headers dependencies
std::vector<std::string> depList;
@@ -1321,9 +1325,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
if (source->GetIsGenerated() &&
!source->GetPropertyAsBool("__CMAKE_GENERATED_BY_CMAKE") &&
!source->GetCustomCommand() &&
- !this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFileName)) {
+ !this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFilePath)) {
this->GetGlobalGenerator()->AddAssumedSourceDependencies(
- sourceFileName, objBuild.OrderOnlyDeps);
+ sourceFilePath, objBuild.OrderOnlyDeps);
}
// For some cases we scan to dynamically discover dependencies.
@@ -1363,6 +1367,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
this->GetPreprocessedFilePath(source, config));
} else {
scanRuleName = this->LanguageScanRule(language, config);
+ ppFileName = cmStrCat(objectFileName, ".ddi.i");
}
cmNinjaBuild ppBuild = GetScanBuildStatement(
@@ -1383,8 +1388,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmSystemTools::GetParentDirectory(source->GetFullPath()));
std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags(
- sourceDirectory, this->GeneratorTarget, language, false, false,
- config);
+ sourceDirectory, this->GeneratorTarget, language, config, false,
+ cmLocalGenerator::IncludePathStyle::Default);
vars["INCLUDES"] = cmStrCat(sourceDirectoryFlag, ' ', vars["INCLUDES"]);
}
@@ -1442,7 +1447,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmProp ispcSuffixProp =
this->GeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX");
- assert(ispcSuffixProp != nullptr);
+ assert(ispcSuffixProp);
std::string ispcHeaderDirectory =
this->GeneratorTarget->GetObjectDirectory(config);
@@ -1573,8 +1578,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
void cmNinjaTargetGenerator::EmitSwiftDependencyInfo(
cmSourceFile const* source, const std::string& config)
{
- std::string const sourceFilePath =
- this->ConvertToNinjaPath(this->GetSourceFilePath(source));
+ std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(source);
std::string const objectFilePath =
this->ConvertToNinjaPath(this->GetObjectFilePath(source, config));
std::string const swiftDepsPath = [source, objectFilePath]() -> std::string {
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index 3a28cef94..4b4cf8d36 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -101,7 +101,7 @@ protected:
const std::string& language,
const std::string& config);
- std::string ConvertToNinjaPath(const std::string& path) const
+ std::string const& ConvertToNinjaPath(const std::string& path) const
{
return this->GetGlobalGenerator()->ConvertToNinjaPath(path);
}
@@ -110,13 +110,18 @@ protected:
return this->GetGlobalGenerator()->MapToNinjaPath();
}
+ std::string ConvertToNinjaAbsPath(std::string path) const
+ {
+ return this->GetGlobalGenerator()->ConvertToNinjaAbsPath(std::move(path));
+ }
+
/// @return the list of link dependency for the given target @a target.
cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage,
const std::string& config,
bool ignoreType = false) const;
/// @return the source file path for the given @a source.
- std::string GetSourceFilePath(cmSourceFile const* source) const;
+ std::string GetCompiledSourceNinjaPath(cmSourceFile const* source) const;
/// @return the object file path for the given @a source.
std::string GetObjectFilePath(cmSourceFile const* source,
diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h
index 320f41bb3..c8a411e1d 100644
--- a/Source/cmNinjaTypes.h
+++ b/Source/cmNinjaTypes.h
@@ -53,6 +53,7 @@ public:
std::string Rule;
cmNinjaDeps Outputs;
cmNinjaDeps ImplicitOuts;
+ cmNinjaDeps WorkDirOuts; // For cmake_ninja_workdir.
cmNinjaDeps ExplicitDeps;
cmNinjaDeps ImplicitDeps;
cmNinjaDeps OrderOnlyDeps;
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 7a04c470b..1f5a7ff4c 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -73,7 +73,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
cmNinjaBuild phonyBuild("phony");
std::vector<std::string> commands;
cmNinjaDeps deps;
- cmNinjaDeps util_outputs(1, utilCommandName);
+ cmGlobalNinjaGenerator::CCOutputs util_outputs(gg);
+ util_outputs.ExplicitOuts.emplace_back(utilCommandName);
bool uses_terminal = false;
{
@@ -86,10 +87,7 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
cmCustomCommandGenerator ccg(ci, fileConfig, lg);
lg->AppendCustomCommandDeps(ccg, deps, fileConfig);
lg->AppendCustomCommandLines(ccg, commands);
- std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
- std::transform(ccByproducts.begin(), ccByproducts.end(),
- std::back_inserter(util_outputs),
- this->MapToNinjaPath());
+ util_outputs.Add(ccg.GetByproducts());
if (ci.GetUsesTerminal()) {
uses_terminal = true;
}
@@ -124,7 +122,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
if (genTarget->Target->GetType() != cmStateEnums::GLOBAL_TARGET) {
lg->AppendTargetOutputs(genTarget, gg->GetByproductsForCleanTarget(),
config);
- std::copy(util_outputs.begin(), util_outputs.end(),
+ std::copy(util_outputs.ExplicitOuts.begin(),
+ util_outputs.ExplicitOuts.end(),
std::back_inserter(gg->GetByproductsForCleanTarget()));
}
lg->AppendTargetDepends(genTarget, deps, config, fileConfig,
@@ -166,10 +165,6 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
return;
}
- for (std::string const& util_output : util_outputs) {
- gg->SeenCustomCommandOutput(util_output);
- }
-
std::string ccConfig;
if (genTarget->Target->IsPerConfig() &&
genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
@@ -180,7 +175,7 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
gg->WriteCustomCommandBuild(
command, desc, "Utility command for " + this->GetTargetName(),
/*depfile*/ "", /*job_pool*/ "", uses_terminal,
- /*restat*/ true, util_outputs, ccConfig, deps);
+ /*restat*/ true, ccConfig, std::move(util_outputs), std::move(deps));
}
phonyBuild.ExplicitDeps.push_back(utilCommandName);
diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx
index a58e2f8cc..bae67e04d 100644
--- a/Source/cmOptionCommand.cxx
+++ b/Source/cmOptionCommand.cxx
@@ -68,6 +68,13 @@ bool cmOptionCommand(std::vector<std::string> const& args,
bool init = cmIsOn(initialValue);
status.GetMakefile().AddCacheDefinition(args[0], init ? "ON" : "OFF",
args[1].c_str(), cmStateEnums::BOOL);
+ if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077) !=
+ cmPolicies::NEW &&
+ status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0126) ==
+ cmPolicies::NEW) {
+ // if there was a definition then remove it
+ status.GetMakefile().GetStateSnapshot().RemoveDefinition(args[0]);
+ }
if (checkAndWarn) {
const auto* existsAfterSet =
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 0369af002..37c4afce0 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -359,7 +359,7 @@ void cmOrderDirectories::SetLinkExtensionInfo(
std::string const& removeExtRegex)
{
this->LinkExtensions = linkExtensions;
- this->RemoveLibraryExtension.compile(removeExtRegex.c_str());
+ this->RemoveLibraryExtension.compile(removeExtRegex);
}
void cmOrderDirectories::CollectOriginalDirectories()
@@ -512,7 +512,7 @@ void cmOrderDirectories::VisitDirectory(unsigned int i)
}
// Now that all directories required to come before this one have
- // been emmitted, emit this directory.
+ // been emitted, emit this directory.
this->OrderedDirectories.push_back(this->OriginalDirectories[i]);
}
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index ec5453716..840fdb9ec 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -9,14 +9,108 @@
#include <vector>
#include "cmState.h"
+#include "cmStateDirectory.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+namespace {
+bool PathEqOrSubDir(std::string const& a, std::string const& b)
+{
+ return (cmSystemTools::ComparePath(a, b) ||
+ cmSystemTools::IsSubDirectory(a, b));
+};
+}
+
cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot)
: StateSnapshot(snapshot)
, LinkScriptShell(false)
{
assert(this->StateSnapshot.IsValid());
+ this->ComputeRelativePathTopSource();
+ this->ComputeRelativePathTopBinary();
+}
+
+void cmOutputConverter::ComputeRelativePathTopSource()
+{
+ // Walk up the buildsystem directory tree to find the highest source
+ // directory that contains the current source directory.
+ cmStateSnapshot snapshot = this->StateSnapshot;
+ for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent();
+ parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) {
+ if (cmSystemTools::IsSubDirectory(
+ snapshot.GetDirectory().GetCurrentSource(),
+ parent.GetDirectory().GetCurrentSource())) {
+ snapshot = parent;
+ }
+ }
+ this->RelativePathTopSource = snapshot.GetDirectory().GetCurrentSource();
+}
+
+void cmOutputConverter::ComputeRelativePathTopBinary()
+{
+ // Walk up the buildsystem directory tree to find the highest binary
+ // directory that contains the current binary directory.
+ cmStateSnapshot snapshot = this->StateSnapshot;
+ for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent();
+ parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) {
+ if (cmSystemTools::IsSubDirectory(
+ snapshot.GetDirectory().GetCurrentBinary(),
+ parent.GetDirectory().GetCurrentBinary())) {
+ snapshot = parent;
+ }
+ }
+
+ this->RelativePathTopBinary = snapshot.GetDirectory().GetCurrentBinary();
+}
+
+std::string const& cmOutputConverter::GetRelativePathTopSource() const
+{
+ return this->RelativePathTopSource;
+}
+
+std::string const& cmOutputConverter::GetRelativePathTopBinary() const
+{
+ return this->RelativePathTopBinary;
+}
+
+void cmOutputConverter::SetRelativePathTopSource(std::string const& top)
+{
+ this->RelativePathTopSource = top;
+}
+
+void cmOutputConverter::SetRelativePathTopBinary(std::string const& top)
+{
+ this->RelativePathTopBinary = top;
+}
+
+std::string cmOutputConverter::MaybeRelativeTo(
+ std::string const& local_path, std::string const& remote_path) const
+{
+ bool bothInBinary =
+ PathEqOrSubDir(local_path, this->RelativePathTopBinary) &&
+ PathEqOrSubDir(remote_path, this->RelativePathTopBinary);
+
+ bool bothInSource =
+ PathEqOrSubDir(local_path, this->RelativePathTopSource) &&
+ PathEqOrSubDir(remote_path, this->RelativePathTopSource);
+
+ if (bothInBinary || bothInSource) {
+ return cmSystemTools::ForceToRelativePath(local_path, remote_path);
+ }
+ return remote_path;
+}
+
+std::string cmOutputConverter::MaybeRelativeToTopBinDir(
+ std::string const& path) const
+{
+ return this->MaybeRelativeTo(this->GetState()->GetBinaryDirectory(), path);
+}
+
+std::string cmOutputConverter::MaybeRelativeToCurBinDir(
+ std::string const& path) const
+{
+ return this->MaybeRelativeTo(
+ this->StateSnapshot.GetDirectory().GetCurrentBinary(), path);
}
std::string cmOutputConverter::ConvertToOutputForExisting(
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index f1a8041ba..865df718b 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -17,6 +17,21 @@ class cmOutputConverter
public:
cmOutputConverter(cmStateSnapshot const& snapshot);
+ /**
+ * Convert the given remote path to a relative path with respect to
+ * one of our common work directories. The path must use forward
+ * slashes and not already be escaped or quoted.
+ * The conversion is skipped if the paths are not both in the source
+ * or both in the binary tree.
+ */
+ std::string MaybeRelativeToTopBinDir(std::string const& path) const;
+ std::string MaybeRelativeToCurBinDir(std::string const& path) const;
+
+ std::string const& GetRelativePathTopSource() const;
+ std::string const& GetRelativePathTopBinary() const;
+ void SetRelativePathTopSource(std::string const& top);
+ void SetRelativePathTopBinary(std::string const& top);
+
enum OutputFormat
{
SHELL,
@@ -102,6 +117,9 @@ public:
};
static FortranPreprocess GetFortranPreprocess(cm::string_view value);
+protected:
+ cmStateSnapshot StateSnapshot;
+
private:
cmState* GetState() const;
@@ -111,7 +129,17 @@ private:
static bool Shell_ArgumentNeedsQuotes(cm::string_view in, int flags);
static std::string Shell_GetArgument(cm::string_view in, int flags);
- cmStateSnapshot StateSnapshot;
-
bool LinkScriptShell;
+
+ // The top-most directories for relative path conversion. Both the
+ // source and destination location of a relative path conversion
+ // must be underneath one of these directories (both under source or
+ // both under binary) in order for the relative path to be evaluated
+ // safely by the build tools.
+ std::string RelativePathTopSource;
+ std::string RelativePathTopBinary;
+ void ComputeRelativePathTopSource();
+ void ComputeRelativePathTopBinary();
+ std::string MaybeRelativeTo(std::string const& local_path,
+ std::string const& remote_path) const;
};
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 2194b0f29..f7c0d2592 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -359,7 +359,27 @@ class cmMakefile;
3, 20, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0120, \
"The WriteCompilerDetectionHeader module is removed.", 3, 20, 0, \
- cmPolicies::WARN)
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0121, \
+ "The list() command now validates parsing of index arguments.", 3, \
+ 21, 0, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0122, \
+ "UseSWIG use standard library name conventions for csharp language.", 3, \
+ 21, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0123, \
+ "ARMClang cpu/arch compile and link flags must be set explicitly.", \
+ 3, 21, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0124, \
+ "foreach() loop variables are only available in the loop scope.", 3, \
+ 21, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0125, \
+ "find_(path|file|library|program) have consistent behavior for " \
+ "cache variables.", \
+ 3, 21, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0126, \
+ "set(CACHE) does not remove a normal variable of the same name.", 3, \
+ 21, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index ed32de9f3..6950c19ef 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -59,6 +59,11 @@ bool cmProjectCommand(std::vector<std::string> const& args,
mf.AddDefinition("PROJECT_NAME", projectName);
+ mf.AddDefinitionBool("PROJECT_IS_TOP_LEVEL", mf.IsRootMakefile());
+ mf.AddCacheDefinition(projectName + "_IS_TOP_LEVEL",
+ mf.IsRootMakefile() ? "ON" : "OFF",
+ "Value Computed by CMake", cmStateEnums::STATIC);
+
// Set the CMAKE_PROJECT_NAME variable to be the highest-level
// project name in the tree. If there are two project commands
// in the same CMakeLists.txt file, and it is the top level
@@ -66,7 +71,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,
// CMAKE_PROJECT_NAME will match PROJECT_NAME, and cmake --build
// will work.
if (!mf.GetDefinition("CMAKE_PROJECT_NAME") || mf.IsRootMakefile()) {
- mf.AddDefinition("CMAKE_PROJECT_NAME", projectName);
+ mf.RemoveDefinition("CMAKE_PROJECT_NAME");
mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName,
"Value Computed by CMake", cmStateEnums::STATIC);
}
@@ -390,7 +395,7 @@ static void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name,
// in the same CMakeLists.txt file, and it is the top level
// CMakeLists.txt file, then go with the last one.
if (!mf.GetDefinition(name) || mf.IsRootMakefile()) {
- mf.AddDefinition(name, value);
+ mf.RemoveDefinition(name);
mf.AddCacheDefinition(name, value, "Value Computed by CMake",
cmStateEnums::STATIC);
}
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index f8d18f27a..77fe87e4c 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -119,7 +119,8 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
target->GetSafeProperty(this->kw().AUTORCC_EXECUTABLE);
// We support Qt4, Qt5 and Qt6
- auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target.get());
+ auto qtVersion =
+ cmQtAutoGenInitializer::GetQtVersion(target.get(), mocExec);
bool const validQt = (qtVersion.first.Major == 4) ||
(qtVersion.first.Major == 5) || (qtVersion.first.Major == 6);
@@ -184,7 +185,7 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
{
cmProp folder =
makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
- if (folder != nullptr) {
+ if (folder) {
target->SetProperty("FOLDER", *folder);
}
}
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index a1816f19f..2894201c9 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -6,8 +6,8 @@
#include <deque>
#include <initializer_list>
#include <map>
-#include <ostream>
#include <set>
+#include <sstream> // for basic_ios, istringstream
#include <string>
#include <unordered_set>
#include <utility>
@@ -114,10 +114,10 @@ bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
// Collect all static_library dependencies from the test target
cmLinkImplementationLibraries const* libs =
testTarget->GetLinkImplementationLibraries(config);
- if (libs != nullptr) {
+ if (libs) {
for (cmLinkItem const& item : libs->Libraries) {
cmGeneratorTarget const* depTarget = item.Target;
- if ((depTarget != nullptr) &&
+ if (depTarget &&
(depTarget->GetType() == cmStateEnums::STATIC_LIBRARY) &&
knownLibs.insert(depTarget).second) {
testLibs.push_back(depTarget);
@@ -294,6 +294,17 @@ bool InfoWriter::Save(std::string const& filename)
return fileStream.Close();
}
+void AddAutogenExecutableToDependencies(
+ cmQtAutoGenInitializer::GenVarsT const& genVars,
+ std::vector<std::string>& dependencies)
+{
+ if (genVars.ExecutableTarget != nullptr) {
+ dependencies.push_back(genVars.ExecutableTarget->Target->GetName());
+ } else if (!genVars.Executable.empty()) {
+ dependencies.push_back(genVars.Executable);
+ }
+}
+
} // End of unnamed namespace
cmQtAutoGenInitializer::cmQtAutoGenInitializer(
@@ -346,15 +357,15 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
{
cmProp folder =
this->Makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
- if (folder == nullptr) {
+ if (!folder) {
folder = this->Makefile->GetState()->GetGlobalProperty(
"AUTOGEN_TARGETS_FOLDER");
}
// Inherit FOLDER property from target (#13688)
- if (folder == nullptr) {
+ if (!folder) {
folder = this->GenTarget->GetProperty("FOLDER");
}
- if (folder != nullptr) {
+ if (folder) {
this->TargetsFolder = *folder;
}
}
@@ -419,12 +430,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);
// Include directory
- this->ConfigFileNames(this->Dir.Include,
- cmStrCat(this->Dir.Build, "/include"), "");
- this->Dir.IncludeGenExp = this->Dir.Include.Default;
- if (this->MultiConfig) {
- this->Dir.IncludeGenExp += "_$<CONFIG>";
- }
+ this->ConfigFileNamesAndGenex(this->Dir.Include, this->Dir.IncludeGenExp,
+ cmStrCat(this->Dir.Build, "/include"), "");
}
// Moc, Uic and _autogen target settings
@@ -483,7 +490,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
for (std::string const& depName : cmExpandedList(deps)) {
// Allow target and file dependencies
auto* depTarget = this->Makefile->FindTargetToUse(depName);
- if (depTarget != nullptr) {
+ if (depTarget) {
this->AutogenTarget.DependTargets.insert(depTarget);
} else {
this->AutogenTarget.DependFiles.insert(depName);
@@ -575,15 +582,9 @@ bool cmQtAutoGenInitializer::InitMoc()
cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");
this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default;
} else {
- this->ConfigFileNames(this->Moc.CompilationFile,
- cmStrCat(this->Dir.Build, "/mocs_compilation"),
- ".cpp");
- if (this->MultiConfig) {
- this->Moc.CompilationFileGenex =
- cmStrCat(this->Dir.Build, "/mocs_compilation_$<CONFIG>.cpp"_s);
- } else {
- this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default;
- }
+ this->ConfigFileNamesAndGenex(
+ this->Moc.CompilationFile, this->Moc.CompilationFileGenex,
+ cmStrCat(this->Dir.Build, "/mocs_compilation"_s), ".cpp"_s);
}
// Moc predefs
@@ -661,7 +662,7 @@ bool cmQtAutoGenInitializer::InitMoc()
return false;
}
// Let the _autogen target depend on the moc executable
- if (this->Moc.ExecutableTarget != nullptr) {
+ if (this->Moc.ExecutableTarget) {
this->AutogenTarget.DependTargets.insert(
this->Moc.ExecutableTarget->Target);
}
@@ -709,7 +710,7 @@ bool cmQtAutoGenInitializer::InitUic()
return false;
}
// Let the _autogen target depend on the uic executable
- if (this->Uic.ExecutableTarget != nullptr) {
+ if (this->Uic.ExecutableTarget) {
this->AutogenTarget.DependTargets.insert(
this->Uic.ExecutableTarget->Target);
}
@@ -864,7 +865,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
auto constexpr locationKind = cmSourceFileLocationKind::Known;
cmSourceFile* sf =
this->Makefile->GetSource(fullPath, locationKind);
- if (sf != nullptr) {
+ if (sf) {
// Check if we know about this header already
if (cm::contains(this->AutogenTarget.Headers, sf)) {
continue;
@@ -879,7 +880,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
sf = this->Makefile->CreateSource(fullPath, false, locationKind);
}
- if (sf != nullptr) {
+ if (sf) {
auto eMuf = makeMUFile(sf, fullPath, muf.Configs, true);
// Only process moc/uic when the parent is processed as well
if (!muf.MocIt) {
@@ -935,9 +936,35 @@ bool cmQtAutoGenInitializer::InitScanFiles()
if (!skipUic) {
// Check if the .ui file has uic options
std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);
- if (!uicOpts.empty()) {
- this->Uic.UiFiles.emplace_back(fullPath, cmExpandedList(uicOpts));
+ if (uicOpts.empty()) {
+ this->Uic.UiFilesNoOptions.emplace_back(fullPath);
+ } else {
+ this->Uic.UiFilesWithOptions.emplace_back(fullPath,
+ cmExpandedList(uicOpts));
}
+
+ auto uiHeaderRelativePath = cmSystemTools::RelativePath(
+ this->LocalGen->GetCurrentSourceDirectory(),
+ cmSystemTools::GetFilenamePath(fullPath));
+
+ // Avoid creating a path containing adjacent slashes
+ if (!uiHeaderRelativePath.empty() &&
+ uiHeaderRelativePath.back() != '/') {
+ uiHeaderRelativePath += '/';
+ }
+
+ auto uiHeaderFilePath = cmStrCat(
+ '/', uiHeaderRelativePath, "ui_"_s,
+ cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s);
+
+ ConfigString uiHeader;
+ std::string uiHeaderGenex;
+ this->ConfigFileNamesAndGenex(
+ uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s),
+ uiHeaderFilePath);
+
+ this->Uic.UiHeaders.emplace_back(
+ std::make_pair(uiHeader, uiHeaderGenex));
} else {
// Register skipped .ui file
this->Uic.SkipUi.insert(fullPath);
@@ -1091,6 +1118,13 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
autogenByproducts.push_back(this->Moc.CompilationFileGenex);
}
+ if (this->Uic.Enabled) {
+ for (const auto& file : this->Uic.UiHeaders) {
+ this->AddGeneratedSource(file.first, this->Uic);
+ autogenByproducts.push_back(file.second);
+ }
+ }
+
// Compose target comment
std::string autogenComment;
{
@@ -1149,6 +1183,42 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
this->Makefile);
}
+ if (!this->Uic.UiFilesNoOptions.empty() ||
+ !this->Uic.UiFilesWithOptions.empty()) {
+ // Add a generated timestamp file
+ ConfigString timestampFile;
+ std::string timestampFileGenex;
+ ConfigFileNamesAndGenex(timestampFile, timestampFileGenex,
+ cmStrCat(this->Dir.Build, "/autouic"_s),
+ ".stamp"_s);
+ this->AddGeneratedSource(timestampFile, this->Uic);
+
+ // Add a step in the pre-build command to touch the timestamp file
+ commandLines.push_back(
+ cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", "touch",
+ timestampFileGenex }));
+
+ // UIC needs to be re-run if any of the known UI files change or the
+ // executable itself has been updated
+ auto uicDependencies = this->Uic.UiFilesNoOptions;
+ for (auto const& uiFile : this->Uic.UiFilesWithOptions) {
+ uicDependencies.push_back(uiFile.first);
+ }
+ AddAutogenExecutableToDependencies(this->Uic, uicDependencies);
+
+ // Add a rule file to cause the target to build if a dependency has
+ // changed, which will trigger the pre-build command to run autogen
+ std::string no_main_dependency;
+ cmCustomCommandLines no_command_lines;
+ this->LocalGen->AddCustomCommandToOutput(
+ timestampFileGenex, uicDependencies, no_main_dependency,
+ no_command_lines, /*comment=*/"", this->Dir.Work.c_str(),
+ /*cmp0116=*/cmPolicies::NEW, /*replace=*/false,
+ /*escapeOldStyle=*/false, /*uses_terminal=*/false,
+ /*command_expand_lists=*/false, /*depfile=*/"", /*job_pool=*/"",
+ stdPipesUTF8);
+ }
+
// Add the pre-build command directly to bypass the OBJECT_LIBRARY
// rejection in cmMakefile::AddCustomCommandToTarget because we know
// PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
@@ -1173,10 +1243,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
for (std::string const& config : this->ConfigsList) {
cmLinkImplementationLibraries const* libs =
this->GenTarget->GetLinkImplementationLibraries(config);
- if (libs != nullptr) {
+ if (libs) {
for (cmLinkItem const& item : libs->Libraries) {
cmGeneratorTarget const* libTarget = item.Target;
- if ((libTarget != nullptr) &&
+ if (libTarget &&
!StaticLibraryCycle(this->GenTarget, libTarget, config)) {
// Increment target config count
commonTargets[libTarget]++;
@@ -1241,16 +1311,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
dependencies.clear();
dependencies.push_back(timestampTargetName);
- if (this->Moc.ExecutableTarget != nullptr) {
- dependencies.push_back(this->Moc.ExecutableTarget->Target->GetName());
- } else if (!this->Moc.Executable.empty()) {
- dependencies.push_back(this->Moc.Executable);
- }
- if (this->Uic.ExecutableTarget != nullptr) {
- dependencies.push_back(this->Uic.ExecutableTarget->Target->GetName());
- } else if (!this->Uic.Executable.empty()) {
- dependencies.push_back(this->Uic.Executable);
- }
+ AddAutogenExecutableToDependencies(this->Moc, dependencies);
+ AddAutogenExecutableToDependencies(this->Uic, dependencies);
// Create the custom command that outputs the timestamp file.
const char timestampFileName[] = "timestamp";
@@ -1589,7 +1651,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end());
info.SetArray("UIC_SKIP", uic_skip);
- info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFiles,
+ info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFilesWithOptions,
[](Json::Value& jval, UicT::UiFileT const& uiFile) {
jval.resize(2u);
jval[0u] = uiFile.first;
@@ -1718,7 +1780,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
// Generate a source group on demand
if (!groupName.empty()) {
sourceGroup = this->Makefile->GetOrCreateSourceGroup(groupName);
- if (sourceGroup == nullptr) {
+ if (!sourceGroup) {
cmSystemTools::Error(
cmStrCat(genNameUpper, " error in ", property,
": Could not find or create the source group ",
@@ -1726,7 +1788,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
}
}
}
- if (sourceGroup != nullptr) {
+ if (sourceGroup) {
sourceGroup->AddGroupFile(fileName);
}
}
@@ -1749,6 +1811,18 @@ void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString,
}
}
+void cmQtAutoGenInitializer::ConfigFileNamesAndGenex(
+ ConfigString& configString, std::string& genex, cm::string_view const prefix,
+ cm::string_view const suffix)
+{
+ this->ConfigFileNames(configString, prefix, suffix);
+ if (this->MultiConfig) {
+ genex = cmStrCat(prefix, "_$<CONFIG>"_s, suffix);
+ } else {
+ genex = configString.Default;
+ }
+}
+
void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString)
{
this->AddCleanFile(configString.Default);
@@ -1759,20 +1833,75 @@ void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString)
}
}
+static cmQtAutoGen::IntegerVersion parseMocVersion(std::string str)
+{
+ cmQtAutoGen::IntegerVersion result;
+
+ static const std::string prelude = "moc ";
+ size_t pos = str.find(prelude);
+ if (pos == std::string::npos) {
+ return result;
+ }
+
+ str.erase(0, prelude.size() + pos);
+ std::istringstream iss(str);
+ std::string major;
+ std::string minor;
+ if (!std::getline(iss, major, '.') || !std::getline(iss, minor, '.')) {
+ return result;
+ }
+
+ result.Major = static_cast<unsigned int>(std::stoi(major));
+ result.Minor = static_cast<unsigned int>(std::stoi(minor));
+ return result;
+}
+
+static cmQtAutoGen::IntegerVersion GetMocVersion(
+ const std::string& mocExecutablePath)
+{
+ std::string capturedStdOut;
+ int exitCode;
+ if (!cmSystemTools::RunSingleCommand({ mocExecutablePath, "--version" },
+ &capturedStdOut, nullptr, &exitCode,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ return {};
+ }
+
+ if (exitCode != 0) {
+ return {};
+ }
+
+ return parseMocVersion(capturedStdOut);
+}
+
+static std::string FindMocExecutableFromMocTarget(cmMakefile* makefile,
+ unsigned int qtMajorVersion)
+{
+ std::string result;
+ const std::string mocTargetName =
+ "Qt" + std::to_string(qtMajorVersion) + "::moc";
+ cmTarget* mocTarget = makefile->FindTargetToUse(mocTargetName);
+ if (mocTarget) {
+ result = mocTarget->GetSafeProperty("IMPORTED_LOCATION");
+ }
+ return result;
+}
+
std::pair<cmQtAutoGen::IntegerVersion, unsigned int>
-cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
+cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target,
+ std::string mocExecutable)
{
// Converts a char ptr to an unsigned int value
auto toUInt = [](const char* const input) -> unsigned int {
unsigned long tmp = 0;
- if (input != nullptr && cmStrToULong(input, &tmp)) {
+ if (input && cmStrToULong(input, &tmp)) {
return static_cast<unsigned int>(tmp);
}
return 0u;
};
auto toUInt2 = [](cmProp input) -> unsigned int {
unsigned long tmp = 0;
- if (input != nullptr && cmStrToULong(*input, &tmp)) {
+ if (input && cmStrToULong(*input, &tmp)) {
return static_cast<unsigned int>(tmp);
}
return 0u;
@@ -1835,6 +1964,21 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
}
}
}
+
+ if (res.first.Major == 0) {
+ // We could not get the version number from variables or directory
+ // properties. This might happen if the find_package call for Qt is wrapped
+ // in a function. Try to find the moc executable path from the available
+ // targets and call "moc --version" to get the Qt version.
+ if (mocExecutable.empty()) {
+ mocExecutable =
+ FindMocExecutableFromMocTarget(target->Makefile, res.second);
+ }
+ if (!mocExecutable.empty()) {
+ res.first = GetMocVersion(mocExecutable);
+ }
+ }
+
return res;
}
@@ -1929,7 +2073,7 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
// Find target
cmGeneratorTarget* genTarget =
this->LocalGen->FindGeneratorTargetToUse(targetName);
- if (genTarget != nullptr) {
+ if (genTarget) {
genVars.ExecutableTargetName = targetName;
genVars.ExecutableTarget = genTarget;
if (genTarget->IsImported()) {
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index f7e126d10..e76817b9c 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -98,9 +98,11 @@ public:
, GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){};
};
- /** @return The detected Qt version and the required Qt major version. */
+ /** @param mocExecutable The file path to the moc executable. Will be used as
+ fallback to query the version
+ @return The detected Qt version and the required Qt major version. */
static std::pair<IntegerVersion, unsigned int> GetQtVersion(
- cmGeneratorTarget const* genTarget);
+ cmGeneratorTarget const* genTarget, std::string mocExecutable);
cmQtAutoGenInitializer(cmQtAutoGenGlobalInitializer* globalInitializer,
cmGeneratorTarget* genTarget,
@@ -141,6 +143,8 @@ private:
void ConfigFileNames(ConfigString& configString, cm::string_view prefix,
cm::string_view suffix);
+ void ConfigFileNamesAndGenex(ConfigString& configString, std::string& genex,
+ cm::string_view prefix, cm::string_view suffix);
void ConfigFileClean(ConfigString& configString);
std::string GetMocBuildPath(MUFile const& muf);
@@ -236,9 +240,12 @@ private:
: GenVarsT(GenT::UIC){};
std::set<std::string> SkipUi;
- std::vector<UiFileT> UiFiles;
+ std::vector<std::string> UiFilesNoOptions;
+ std::vector<UiFileT> UiFilesWithOptions;
ConfigStrings<std::vector<std::string>> Options;
std::vector<std::string> SearchPaths;
+ std::vector<std::pair<ConfigString /*ui header*/, std::string /*genex*/>>
+ UiHeaders;
} Uic;
/** rcc variables. */
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index 6e88e266f..568926e3c 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -116,7 +116,7 @@ bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename)
bool success = true;
std::string const dirName = cmSystemTools::GetFilenamePath(filename);
if (!dirName.empty()) {
- success = cmSystemTools::MakeDirectory(dirName);
+ success = static_cast<bool>(cmSystemTools::MakeDirectory(dirName));
}
return success;
}
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index f5831628d..f5c195fd1 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -1588,14 +1588,14 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
};
// Vicinity of the source
- if (findUi(cmStrCat(sourceDirPrefix, this->UiName))) {
- return true;
- }
if (!includePrefix.empty()) {
if (findUi(cmStrCat(sourceDirPrefix, includePrefix, this->UiName))) {
return true;
}
}
+ if (findUi(cmStrCat(sourceDirPrefix, this->UiName))) {
+ return true;
+ }
// Additional AUTOUIC search paths
auto const& searchPaths = this->UicConst().SearchPaths;
if (!searchPaths.empty()) {
@@ -2723,6 +2723,9 @@ void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap)
std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const
{
std::lock_guard<std::mutex> guard(this->CMakeLibMutex_);
+#if defined(__NVCOMPILER)
+ static_cast<void>(guard); // convince compiler var is used
+#endif
return cmSystemTools::CollapseFullPath(path,
this->ProjectDirs().CurrentSource);
}
@@ -2962,6 +2965,9 @@ std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile(
const char* filePath)
{
std::lock_guard<std::mutex> guard(this->CMakeLibMutex_);
+#if defined(__NVCOMPILER)
+ static_cast<void>(guard); // convince compiler var is used
+#endif
auto const content = cmReadGccDepfile(filePath);
if (!content || content->empty()) {
return {};
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index d00bbdf04..7480aebe2 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -6,6 +6,7 @@
#include <utility>
#include "cmOutputConverter.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmRulePlaceholderExpander::cmRulePlaceholderExpander(
@@ -280,6 +281,13 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
this->VariableMappings["CMAKE_" + compIt->second +
"_COMPILE_OPTIONS_SYSROOT"];
+ if (compIt->second == replaceValues.Language && replaceValues.Launcher) {
+ // Add launcher as part of expansion so that it always appears
+ // immediately before the command itself, regardless of whether the
+ // overall rule template contains other content at the front.
+ ret = cmStrCat(replaceValues.Launcher, " ", ret);
+ }
+
// if there are required arguments to the compiler add it
// to the compiler string
if (!compilerArg1.empty()) {
@@ -317,7 +325,17 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
auto mapIt = this->VariableMappings.find(variable);
if (mapIt != this->VariableMappings.end()) {
if (variable.find("_FLAG") == std::string::npos) {
- return outputConverter->ConvertToOutputForExisting(mapIt->second);
+ std::string ret =
+ outputConverter->ConvertToOutputForExisting(mapIt->second);
+
+ if (replaceValues.Launcher && variable == "CMAKE_LINKER") {
+ // Add launcher as part of expansion so that it always appears
+ // immediately before the command itself, regardless of whether the
+ // overall rule template contains other content at the front.
+ ret = cmStrCat(replaceValues.Launcher, " ", ret);
+ }
+
+ return ret;
}
return mapIt->second;
}
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index f8dc36837..c22e0fa9f 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -67,6 +67,7 @@ public:
const char* ISPCHeader = nullptr;
const char* Fatbinary = nullptr;
const char* RegisterFile = nullptr;
+ const char* Launcher = nullptr;
};
// Expand rule variables in CMake of the type found in language rules
diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx
index 472f23469..26f255da0 100644
--- a/Source/cmRuntimeDependencyArchive.cxx
+++ b/Source/cmRuntimeDependencyArchive.cxx
@@ -115,7 +115,10 @@ cmRuntimeDependencyArchive::cmRuntimeDependencyArchive(
const std::vector<std::string>& preIncludeRegexes,
const std::vector<std::string>& preExcludeRegexes,
const std::vector<std::string>& postIncludeRegexes,
- const std::vector<std::string>& postExcludeRegexes)
+ const std::vector<std::string>& postExcludeRegexes,
+ std::vector<std::string> postIncludeFiles,
+ std::vector<std::string> postExcludeFiles,
+ std::vector<std::string> postExcludeFilesStrict)
: Status(status)
, SearchDirectories(std::move(searchDirectories))
, BundleExecutable(std::move(bundleExecutable))
@@ -123,6 +126,9 @@ cmRuntimeDependencyArchive::cmRuntimeDependencyArchive(
, PreExcludeRegexes(preExcludeRegexes.size())
, PostIncludeRegexes(postIncludeRegexes.size())
, PostExcludeRegexes(postExcludeRegexes.size())
+ , PostIncludeFiles(std::move(postIncludeFiles))
+ , PostExcludeFiles(std::move(postExcludeFiles))
+ , PostExcludeFilesStrict(std::move(postExcludeFilesStrict))
{
std::transform(preIncludeRegexes.begin(), preIncludeRegexes.end(),
this->PreIncludeRegexes.begin(), TransformCompile);
@@ -192,25 +198,26 @@ void cmRuntimeDependencyArchive::SetError(const std::string& e)
this->Status.SetError(e);
}
-std::string cmRuntimeDependencyArchive::GetBundleExecutable()
+const std::string& cmRuntimeDependencyArchive::GetBundleExecutable() const
{
return this->BundleExecutable;
}
const std::vector<std::string>&
-cmRuntimeDependencyArchive::GetSearchDirectories()
+cmRuntimeDependencyArchive::GetSearchDirectories() const
{
return this->SearchDirectories;
}
-std::string cmRuntimeDependencyArchive::GetGetRuntimeDependenciesTool()
+const std::string& cmRuntimeDependencyArchive::GetGetRuntimeDependenciesTool()
+ const
{
return this->GetMakefile()->GetSafeDefinition(
"CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL");
}
bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand(
- const std::string& search, std::vector<std::string>& command)
+ const std::string& search, std::vector<std::string>& command) const
{
// First see if it was supplied by the user
std::string toolCommand = this->GetMakefile()->GetSafeDefinition(
@@ -303,47 +310,53 @@ bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand(
return false;
}
-bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name)
+bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name) const
{
cmsys::RegularExpressionMatch match;
-
- for (auto const& regex : this->PreIncludeRegexes) {
- if (regex.find(name.c_str(), match)) {
- return false;
- }
- }
-
- for (auto const& regex : this->PreExcludeRegexes) {
- if (regex.find(name.c_str(), match)) {
- return true;
- }
- }
-
- return false;
+ auto const regexMatch =
+ [&match, name](const cmsys::RegularExpression& regex) -> bool {
+ return regex.find(name.c_str(), match);
+ };
+ auto const regexSearch =
+ [&regexMatch](
+ const std::vector<cmsys::RegularExpression>& regexes) -> bool {
+ return std::any_of(regexes.begin(), regexes.end(), regexMatch);
+ };
+
+ return !regexSearch(this->PreIncludeRegexes) &&
+ regexSearch(this->PreExcludeRegexes);
}
-bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name)
+bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name) const
{
cmsys::RegularExpressionMatch match;
-
- for (auto const& regex : this->PostIncludeRegexes) {
- if (regex.find(name.c_str(), match)) {
- return false;
- }
- }
-
- for (auto const& regex : this->PostExcludeRegexes) {
- if (regex.find(name.c_str(), match)) {
- return true;
- }
- }
-
- return false;
+ auto const regexMatch =
+ [&match, name](const cmsys::RegularExpression& regex) -> bool {
+ return regex.find(name.c_str(), match);
+ };
+ auto const regexSearch =
+ [&regexMatch](
+ const std::vector<cmsys::RegularExpression>& regexes) -> bool {
+ return std::any_of(regexes.begin(), regexes.end(), regexMatch);
+ };
+ auto const fileMatch = [name](const std::string& file) -> bool {
+ return cmSystemTools::SameFile(file, name);
+ };
+ auto const fileSearch =
+ [&fileMatch](const std::vector<std::string>& files) -> bool {
+ return std::any_of(files.begin(), files.end(), fileMatch);
+ };
+
+ return fileSearch(this->PostExcludeFilesStrict) ||
+ (!(regexSearch(this->PostIncludeRegexes) ||
+ fileSearch(this->PostIncludeFiles)) &&
+ (regexSearch(this->PostExcludeRegexes) ||
+ fileSearch(this->PostExcludeFiles)));
}
-void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name,
- const std::string& path,
- bool& unique)
+void cmRuntimeDependencyArchive::AddResolvedPath(
+ const std::string& name, const std::string& path, bool& unique,
+ std::vector<std::string> rpaths)
{
auto it = this->ResolvedPaths.emplace(name, std::set<std::string>{}).first;
unique = true;
@@ -354,6 +367,7 @@ void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name,
}
}
it->second.insert(path);
+ this->RPaths[path] = std::move(rpaths);
}
void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name)
@@ -361,18 +375,33 @@ void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name)
this->UnresolvedPaths.insert(name);
}
-cmMakefile* cmRuntimeDependencyArchive::GetMakefile()
+cmMakefile* cmRuntimeDependencyArchive::GetMakefile() const
{
return &this->Status.GetMakefile();
}
const std::map<std::string, std::set<std::string>>&
-cmRuntimeDependencyArchive::GetResolvedPaths()
+cmRuntimeDependencyArchive::GetResolvedPaths() const
{
return this->ResolvedPaths;
}
const std::set<std::string>& cmRuntimeDependencyArchive::GetUnresolvedPaths()
+ const
{
return this->UnresolvedPaths;
}
+
+const std::map<std::string, std::vector<std::string>>&
+cmRuntimeDependencyArchive::GetRPaths() const
+{
+ return this->RPaths;
+}
+
+bool cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
+ const std::string& platform)
+{
+ static const std::set<std::string> supportedPlatforms = { "Windows", "Linux",
+ "Darwin" };
+ return supportedPlatforms.count(platform);
+}
diff --git a/Source/cmRuntimeDependencyArchive.h b/Source/cmRuntimeDependencyArchive.h
index 7f3b8e9bd..b170815b4 100644
--- a/Source/cmRuntimeDependencyArchive.h
+++ b/Source/cmRuntimeDependencyArchive.h
@@ -25,7 +25,10 @@ public:
const std::vector<std::string>& preIncludeRegexes,
const std::vector<std::string>& preExcludeRegexes,
const std::vector<std::string>& postIncludeRegexes,
- const std::vector<std::string>& postExcludeRegexes);
+ const std::vector<std::string>& postExcludeRegexes,
+ std::vector<std::string> postIncludeFiles,
+ std::vector<std::string> postExcludeFiles,
+ std::vector<std::string> postExcludeFilesStrict);
bool Prepare();
bool GetRuntimeDependencies(const std::vector<std::string>& executables,
const std::vector<std::string>& libraries,
@@ -33,21 +36,24 @@ public:
void SetError(const std::string& e);
- std::string GetBundleExecutable();
- const std::vector<std::string>& GetSearchDirectories();
- std::string GetGetRuntimeDependenciesTool();
- bool GetGetRuntimeDependenciesCommand(const std::string& search,
- std::vector<std::string>& command);
- bool IsPreExcluded(const std::string& name);
- bool IsPostExcluded(const std::string& name);
+ const std::string& GetBundleExecutable() const;
+ const std::vector<std::string>& GetSearchDirectories() const;
+ const std::string& GetGetRuntimeDependenciesTool() const;
+ bool GetGetRuntimeDependenciesCommand(
+ const std::string& search, std::vector<std::string>& command) const;
+ bool IsPreExcluded(const std::string& name) const;
+ bool IsPostExcluded(const std::string& name) const;
void AddResolvedPath(const std::string& name, const std::string& path,
- bool& unique);
+ bool& unique, std::vector<std::string> rpaths = {});
void AddUnresolvedPath(const std::string& name);
- cmMakefile* GetMakefile();
- const std::map<std::string, std::set<std::string>>& GetResolvedPaths();
- const std::set<std::string>& GetUnresolvedPaths();
+ cmMakefile* GetMakefile() const;
+ const std::map<std::string, std::set<std::string>>& GetResolvedPaths() const;
+ const std::set<std::string>& GetUnresolvedPaths() const;
+ const std::map<std::string, std::vector<std::string>>& GetRPaths() const;
+
+ static bool PlatformSupportsRuntimeDependencies(const std::string& platform);
private:
cmExecutionStatus& Status;
@@ -62,6 +68,10 @@ private:
std::vector<cmsys::RegularExpression> PreExcludeRegexes;
std::vector<cmsys::RegularExpression> PostIncludeRegexes;
std::vector<cmsys::RegularExpression> PostExcludeRegexes;
+ std::vector<std::string> PostIncludeFiles;
+ std::vector<std::string> PostExcludeFiles;
+ std::vector<std::string> PostExcludeFilesStrict;
std::map<std::string, std::set<std::string>> ResolvedPaths;
std::set<std::string> UnresolvedPaths;
+ std::map<std::string, std::vector<std::string>> RPaths;
};
diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx
index f988fe45f..6fcbce5f1 100644
--- a/Source/cmScanDepFormat.cxx
+++ b/Source/cmScanDepFormat.cxx
@@ -5,6 +5,11 @@
#include <cctype>
#include <cstdio>
+#include <utility>
+
+#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/string_view>
#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
@@ -69,12 +74,14 @@ static Json::Value EncodeFilename(std::string const& path)
return false; \
} \
\
- if (!work_directory.empty() && !cmSystemTools::FileIsFullPath(res)) { \
- res = cmStrCat(work_directory, '/', res); \
+ if (work_directory && !work_directory->empty() && \
+ !cmSystemTools::FileIsFullPath(res)) { \
+ res = cmStrCat(*work_directory, '/', res); \
} \
} while (0)
-bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmSourceInfo* info)
+bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp,
+ cmScanDepInfo* info)
{
Json::Value ppio;
Json::Value const& ppi = ppio;
@@ -105,10 +112,12 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmSourceInfo* info)
}
for (auto const& rule : rules) {
- std::string work_directory;
+ cm::optional<std::string> work_directory;
Json::Value const& workdir = rule["work-directory"];
if (workdir.isString()) {
- PARSE_BLOB(workdir, work_directory);
+ std::string wd;
+ PARSE_BLOB(workdir, wd);
+ work_directory = std::move(wd);
} else if (!workdir.isNull()) {
cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
arg_pp,
@@ -116,75 +125,146 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmSourceInfo* info)
return false;
}
- Json::Value const& depends = rule["depends"];
- if (depends.isArray()) {
- std::string depend_filename;
- for (auto const& depend : depends) {
- PARSE_FILENAME(depend, depend_filename);
- info->Includes.push_back(depend_filename);
+ if (rule.isMember("primary-output")) {
+ Json::Value const& primary_output = rule["primary-output"];
+ PARSE_FILENAME(primary_output, info->PrimaryOutput);
+ }
+
+ if (rule.isMember("outputs")) {
+ Json::Value const& outputs = rule["outputs"];
+ if (outputs.isArray()) {
+ for (auto const& output : outputs) {
+ std::string extra_output;
+ PARSE_FILENAME(output, extra_output);
+
+ info->ExtraOutputs.emplace_back(extra_output);
+ }
}
}
- if (rule.isMember("future-compile")) {
- Json::Value const& future_compile = rule["future-compile"];
+ if (rule.isMember("provides")) {
+ Json::Value const& provides = rule["provides"];
+ if (!provides.isArray()) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
+ ": provides is not an array"));
+ return false;
+ }
- if (future_compile.isMember("outputs")) {
- Json::Value const& outputs = future_compile["outputs"];
- if (outputs.isArray()) {
- if (outputs.empty()) {
+ for (auto const& provide : provides) {
+ cmSourceReqInfo provide_info;
+
+ Json::Value const& logical_name = provide["logical-name"];
+ PARSE_BLOB(logical_name, provide_info.LogicalName);
+
+ if (provide.isMember("compiled-module-path")) {
+ Json::Value const& compiled_module_path =
+ provide["compiled-module-path"];
+ PARSE_FILENAME(compiled_module_path,
+ provide_info.CompiledModulePath);
+ }
+
+ if (provide.isMember("unique-on-source-path")) {
+ Json::Value const& unique_on_source_path =
+ provide["unique-on-source-path"];
+ if (!unique_on_source_path.isBool()) {
cmSystemTools::Error(
cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
- ": expected at least one 1 output"));
+ ": unique-on-source-path is not a boolean"));
return false;
}
+ provide_info.UseSourcePath = unique_on_source_path.asBool();
+ } else {
+ provide_info.UseSourcePath = false;
+ }
- PARSE_FILENAME(outputs[0], info->PrimaryOutput);
+ if (provide.isMember("source-path")) {
+ Json::Value const& source_path = provide["source-path"];
+ PARSE_FILENAME(source_path, provide_info.SourcePath);
+ } else if (provide_info.UseSourcePath) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
+ ": source-path is missing"));
+ return false;
}
+
+ info->Provides.push_back(provide_info);
}
+ }
- if (future_compile.isMember("provides")) {
- Json::Value const& provides = future_compile["provides"];
- if (provides.isArray()) {
- for (auto const& provide : provides) {
- cmSourceReqInfo provide_info;
-
- Json::Value const& logical_name = provide["logical-name"];
- PARSE_BLOB(logical_name, provide_info.LogicalName);
-
- if (provide.isMember("compiled-module-path")) {
- Json::Value const& compiled_module_path =
- provide["compiled-module-path"];
- PARSE_FILENAME(compiled_module_path,
- provide_info.CompiledModulePath);
- } else {
- provide_info.CompiledModulePath =
- cmStrCat(provide_info.LogicalName, ".mod");
- }
-
- info->Provides.push_back(provide_info);
- }
- }
+ if (rule.isMember("requires")) {
+ Json::Value const& reqs = rule["requires"];
+ if (!reqs.isArray()) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
+ ": requires is not an array"));
+ return false;
}
- if (future_compile.isMember("requires")) {
- Json::Value const& reqs = future_compile["requires"];
- if (reqs.isArray()) {
- for (auto const& require : reqs) {
- cmSourceReqInfo require_info;
+ for (auto const& require : reqs) {
+ cmSourceReqInfo require_info;
+
+ Json::Value const& logical_name = require["logical-name"];
+ PARSE_BLOB(logical_name, require_info.LogicalName);
+
+ if (require.isMember("compiled-module-path")) {
+ Json::Value const& compiled_module_path =
+ require["compiled-module-path"];
+ PARSE_FILENAME(compiled_module_path,
+ require_info.CompiledModulePath);
+ }
+
+ if (require.isMember("unique-on-source-path")) {
+ Json::Value const& unique_on_source_path =
+ require["unique-on-source-path"];
+ if (!unique_on_source_path.isBool()) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
+ ": unique-on-source-path is not a boolean"));
+ return false;
+ }
+ require_info.UseSourcePath = unique_on_source_path.asBool();
+ } else {
+ require_info.UseSourcePath = false;
+ }
- Json::Value const& logical_name = require["logical-name"];
- PARSE_BLOB(logical_name, require_info.LogicalName);
+ if (require.isMember("source-path")) {
+ Json::Value const& source_path = require["source-path"];
+ PARSE_FILENAME(source_path, require_info.SourcePath);
+ } else if (require_info.UseSourcePath) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
+ ": source-path is missing"));
+ return false;
+ }
- if (require.isMember("compiled-module-path")) {
- Json::Value const& compiled_module_path =
- require["compiled-module-path"];
- PARSE_FILENAME(compiled_module_path,
- require_info.CompiledModulePath);
- }
+ if (require.isMember("lookup-method")) {
+ Json::Value const& lookup_method = require["lookup-method"];
+ if (!lookup_method.isString()) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
+ ": lookup-method is not a string"));
+ return false;
+ }
- info->Requires.push_back(require_info);
+ std::string lookup_method_str = lookup_method.asString();
+ if (lookup_method_str == "by-name"_s) {
+ require_info.Method = LookupMethod::ByName;
+ } else if (lookup_method_str == "include-angle"_s) {
+ require_info.Method = LookupMethod::IncludeAngle;
+ } else if (lookup_method_str == "include-quote"_s) {
+ require_info.Method = LookupMethod::IncludeQuote;
+ } else {
+ cmSystemTools::Error(cmStrCat(
+ "-E cmake_ninja_dyndep failed to parse ", arg_pp,
+ ": lookup-method is not a valid: ", lookup_method_str));
+ return false;
}
+ } else if (require_info.UseSourcePath) {
+ require_info.Method = LookupMethod::ByName;
}
+
+ info->Requires.push_back(require_info);
}
}
}
@@ -194,8 +274,7 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmSourceInfo* info)
}
bool cmScanDepFormat_P1689_Write(std::string const& path,
- std::string const& input,
- cmSourceInfo const& info)
+ cmScanDepInfo const& info)
{
Json::Value ddi(Json::objectValue);
ddi["version"] = 0;
@@ -204,53 +283,66 @@ bool cmScanDepFormat_P1689_Write(std::string const& path,
Json::Value& rules = ddi["rules"] = Json::arrayValue;
Json::Value rule(Json::objectValue);
- Json::Value& inputs = rule["inputs"] = Json::arrayValue;
- inputs.append(EncodeFilename(input));
- Json::Value& rule_outputs = rule["outputs"] = Json::arrayValue;
- rule_outputs.append(EncodeFilename(path));
+ rule["primary-output"] = EncodeFilename(info.PrimaryOutput);
- Json::Value& depends = rule["depends"] = Json::arrayValue;
- for (auto const& include : info.Includes) {
- depends.append(EncodeFilename(include));
+ Json::Value& rule_outputs = rule["outputs"] = Json::arrayValue;
+ for (auto const& output : info.ExtraOutputs) {
+ rule_outputs.append(EncodeFilename(output));
}
- Json::Value& future_compile = rule["future-compile"] = Json::objectValue;
-
- Json::Value& outputs = future_compile["outputs"] = Json::arrayValue;
- outputs.append(info.PrimaryOutput);
-
- Json::Value& provides = future_compile["provides"] = Json::arrayValue;
+ Json::Value& provides = rule["provides"] = Json::arrayValue;
for (auto const& provide : info.Provides) {
Json::Value provide_obj(Json::objectValue);
auto const encoded = EncodeFilename(provide.LogicalName);
provide_obj["logical-name"] = encoded;
- if (provide.CompiledModulePath.empty()) {
- provide_obj["compiled-module-path"] = encoded;
- } else {
+ if (!provide.CompiledModulePath.empty()) {
provide_obj["compiled-module-path"] =
EncodeFilename(provide.CompiledModulePath);
}
- // TODO: Source file tracking. See below.
+ if (provide.UseSourcePath) {
+ provide_obj["unique-on-source-path"] = true;
+ provide_obj["source-path"] = EncodeFilename(provide.SourcePath);
+ } else if (!provide.SourcePath.empty()) {
+ provide_obj["source-path"] = EncodeFilename(provide.SourcePath);
+ }
provides.append(provide_obj);
}
- Json::Value& reqs = future_compile["requires"] = Json::arrayValue;
+ Json::Value& reqs = rule["requires"] = Json::arrayValue;
for (auto const& require : info.Requires) {
Json::Value require_obj(Json::objectValue);
auto const encoded = EncodeFilename(require.LogicalName);
require_obj["logical-name"] = encoded;
- if (require.CompiledModulePath.empty()) {
- require_obj["compiled-module-path"] = encoded;
- } else {
+ if (!require.CompiledModulePath.empty()) {
require_obj["compiled-module-path"] =
EncodeFilename(require.CompiledModulePath);
}
- // TODO: Source filename inclusion. Requires collating with the provides
- // filenames (as a sanity check if available on both sides).
+ if (require.UseSourcePath) {
+ require_obj["unique-on-source-path"] = true;
+ require_obj["source-path"] = EncodeFilename(require.SourcePath);
+ } else if (!require.SourcePath.empty()) {
+ require_obj["source-path"] = EncodeFilename(require.SourcePath);
+ }
+
+ const char* lookup_method = nullptr;
+ switch (require.Method) {
+ case LookupMethod::ByName:
+ // No explicit value needed for the default.
+ break;
+ case LookupMethod::IncludeAngle:
+ lookup_method = "include-angle";
+ break;
+ case LookupMethod::IncludeQuote:
+ lookup_method = "include-quote";
+ break;
+ }
+ if (lookup_method) {
+ require_obj["lookup-method"] = lookup_method;
+ }
reqs.append(require_obj);
}
diff --git a/Source/cmScanDepFormat.h b/Source/cmScanDepFormat.h
index 1ad0ecf73..dae28d950 100644
--- a/Source/cmScanDepFormat.h
+++ b/Source/cmScanDepFormat.h
@@ -5,26 +5,33 @@
#include <string>
#include <vector>
+enum class LookupMethod
+{
+ ByName,
+ IncludeAngle,
+ IncludeQuote,
+};
+
struct cmSourceReqInfo
{
std::string LogicalName;
+ std::string SourcePath;
std::string CompiledModulePath;
+ bool UseSourcePath = false;
+ LookupMethod Method = LookupMethod::ByName;
};
-struct cmSourceInfo
+struct cmScanDepInfo
{
std::string PrimaryOutput;
+ std::vector<std::string> ExtraOutputs;
// Set of provided and required modules.
std::vector<cmSourceReqInfo> Provides;
std::vector<cmSourceReqInfo> Requires;
-
- // Set of files included in the translation unit.
- std::vector<std::string> Includes;
};
bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp,
- cmSourceInfo* info);
+ cmScanDepInfo* info);
bool cmScanDepFormat_P1689_Write(std::string const& path,
- std::string const& input,
- cmSourceInfo const& info);
+ cmScanDepInfo const& info);
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 76a5ded89..32ed68715 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -175,7 +175,7 @@ private:
#define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$"
#define CM_SOURCE_REGEX \
- "\\.(C|F|M|c|c\\+\\+|cc|cpp|mpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|" \
+ "\\.(C|F|M|c|c\\+\\+|cc|cpp|mpp|cxx|ixx|cppm|cu|f|f90|for|fpp|ftn|m|mm|" \
"rc|def|r|odl|idl|hpj|bat)$"
#define CM_PCH_REGEX "cmake_pch(_[^.]+)?\\.(h|hxx)$"
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index bf6925e87..37ed4c130 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -36,6 +36,9 @@ const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE(
const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE(
FEATURE_STRING) };
+
+const char* const HIP_FEATURES[] = { nullptr FOR_EACH_HIP_FEATURE(
+ FEATURE_STRING) };
#undef FEATURE_STRING
struct StandardNeeded
@@ -62,7 +65,7 @@ struct StanardLevelComputer
, Levels(std::move(levels))
, LevelsAsStrings(std::move(levelsStr))
{
- assert(levels.size() == levelsStr.size());
+ assert(this->Levels.size() == this->LevelsAsStrings.size());
}
std::string GetCompileOptionDef(cmMakefile* makefile,
@@ -184,7 +187,7 @@ struct StanardLevelComputer
auto needed = this->HighestStandardNeeded(makefile, feature);
cmProp existingStandard = currentLangStandardValue;
- if (existingStandard == nullptr) {
+ if (!existingStandard) {
cmProp defaultStandard = makefile->GetDefinition(
cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT"));
if (cmNonempty(defaultStandard)) {
@@ -306,10 +309,10 @@ struct StanardLevelComputer
};
std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping =
- {
- { "C",
- StanardLevelComputer{ "C", std::vector<int>{ 90, 99, 11 },
- std::vector<std::string>{ "90", "99", "11" } } },
+ { { "C",
+ StanardLevelComputer{
+ "C", std::vector<int>{ 90, 99, 11, 17, 23 },
+ std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
{ "CXX",
StanardLevelComputer{
"CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
@@ -319,13 +322,17 @@ std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping =
"CUDA", std::vector<int>{ 03, 11, 14, 17, 20, 23 },
std::vector<std::string>{ "03", "11", "14", "17", "20", "23" } } },
{ "OBJC",
- StanardLevelComputer{ "OBJC", std::vector<int>{ 90, 99, 11 },
- std::vector<std::string>{ "90", "99", "11" } } },
+ StanardLevelComputer{
+ "OBJC", std::vector<int>{ 90, 99, 11, 17, 23 },
+ std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
{ "OBJCXX",
StanardLevelComputer{
"OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
- };
+ { "HIP",
+ StanardLevelComputer{
+ "HIP", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
+ std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } } };
}
std::string cmStandardLevelResolver::GetCompileOptionDef(
@@ -433,6 +440,13 @@ bool cmStandardLevelResolver::CompileFeatureKnown(
lang = "CUDA";
return true;
}
+ bool isHIPFeature =
+ std::find_if(cm::cbegin(HIP_FEATURES) + 1, cm::cend(HIP_FEATURES),
+ cmStrCmp(feature)) != cm::cend(HIP_FEATURES);
+ if (isHIPFeature) {
+ lang = "HIP";
+ return true;
+ }
std::ostringstream e;
if (error) {
e << "specified";
diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h
index b871f5fca..417f14d81 100644
--- a/Source/cmStandardLexer.h
+++ b/Source/cmStandardLexer.h
@@ -50,6 +50,11 @@
# endif
#endif
+#if defined(__NVCOMPILER)
+# pragma diag_suppress 111 /* statement is unreachable */
+# pragma diag_suppress 550 /* variable set but never used */
+#endif
+
/* Make sure isatty is available. */
#if defined(_WIN32) && !defined(__CYGWIN__)
# include <io.h>
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 929b0fba9..ce6eb311e 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -286,6 +286,7 @@ cmStateSnapshot cmState::Reset()
it->LinkDirectoriesBacktraces.clear();
it->DirectoryEnd = pos;
it->NormalTargetNames.clear();
+ it->ImportedTargetNames.clear();
it->Properties.Clear();
it->Children.clear();
}
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 7ce362a58..c898dd475 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -8,7 +8,9 @@
#include <vector>
#include <cm/iterator>
+#include <cm/string_view>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmAlgorithms.h"
#include "cmProperty.h"
@@ -24,68 +26,6 @@ static std::string const kBUILDSYSTEM_TARGETS = "BUILDSYSTEM_TARGETS";
static std::string const kSOURCE_DIR = "SOURCE_DIR";
static std::string const kSUBDIRECTORIES = "SUBDIRECTORIES";
-void cmStateDirectory::ComputeRelativePathTopSource()
-{
- // Relative path conversion inside the source tree is not used to
- // construct relative paths passed to build tools so it is safe to use
- // even when the source is a network path.
-
- cmStateSnapshot snapshot = this->Snapshot_;
- std::vector<cmStateSnapshot> snapshots;
- snapshots.push_back(snapshot);
- while (true) {
- snapshot = snapshot.GetBuildsystemDirectoryParent();
- if (snapshot.IsValid()) {
- snapshots.push_back(snapshot);
- } else {
- break;
- }
- }
-
- std::string result = snapshots.front().GetDirectory().GetCurrentSource();
-
- for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) {
- std::string currentSource = snp.GetDirectory().GetCurrentSource();
- if (cmSystemTools::IsSubDirectory(result, currentSource)) {
- result = currentSource;
- }
- }
- this->DirectoryState->RelativePathTopSource = result;
-}
-
-void cmStateDirectory::ComputeRelativePathTopBinary()
-{
- cmStateSnapshot snapshot = this->Snapshot_;
- std::vector<cmStateSnapshot> snapshots;
- snapshots.push_back(snapshot);
- while (true) {
- snapshot = snapshot.GetBuildsystemDirectoryParent();
- if (snapshot.IsValid()) {
- snapshots.push_back(snapshot);
- } else {
- break;
- }
- }
-
- std::string result = snapshots.front().GetDirectory().GetCurrentBinary();
-
- for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) {
- std::string currentBinary = snp.GetDirectory().GetCurrentBinary();
- if (cmSystemTools::IsSubDirectory(result, currentBinary)) {
- result = currentBinary;
- }
- }
-
- // The current working directory on Windows cannot be a network
- // path. Therefore relative paths cannot work when the binary tree
- // is a network path.
- if (result.size() < 2 || result.substr(0, 2) != "//") {
- this->DirectoryState->RelativePathTopBinary = result;
- } else {
- this->DirectoryState->RelativePathTopBinary.clear();
- }
-}
-
std::string const& cmStateDirectory::GetCurrentSource() const
{
return this->DirectoryState->Location;
@@ -97,9 +37,6 @@ void cmStateDirectory::SetCurrentSource(std::string const& dir)
loc = dir;
cmSystemTools::ConvertToUnixSlashes(loc);
loc = cmSystemTools::CollapseFullPath(loc);
-
- this->ComputeRelativePathTopSource();
-
this->Snapshot_.SetDefinition("CMAKE_CURRENT_SOURCE_DIR", loc);
}
@@ -114,60 +51,9 @@ void cmStateDirectory::SetCurrentBinary(std::string const& dir)
loc = dir;
cmSystemTools::ConvertToUnixSlashes(loc);
loc = cmSystemTools::CollapseFullPath(loc);
-
- this->ComputeRelativePathTopBinary();
-
this->Snapshot_.SetDefinition("CMAKE_CURRENT_BINARY_DIR", loc);
}
-std::string const& cmStateDirectory::GetRelativePathTopSource() const
-{
- return this->DirectoryState->RelativePathTopSource;
-}
-
-std::string const& cmStateDirectory::GetRelativePathTopBinary() const
-{
- return this->DirectoryState->RelativePathTopBinary;
-}
-
-void cmStateDirectory::SetRelativePathTopSource(const char* dir)
-{
- this->DirectoryState->RelativePathTopSource = dir;
-}
-
-void cmStateDirectory::SetRelativePathTopBinary(const char* dir)
-{
- this->DirectoryState->RelativePathTopBinary = dir;
-}
-
-bool cmStateDirectory::ContainsBoth(std::string const& local_path,
- std::string const& remote_path) const
-{
- auto PathEqOrSubDir = [](std::string const& a, std::string const& b) {
- return (cmSystemTools::ComparePath(a, b) ||
- cmSystemTools::IsSubDirectory(a, b));
- };
-
- bool bothInBinary =
- PathEqOrSubDir(local_path, this->GetRelativePathTopBinary()) &&
- PathEqOrSubDir(remote_path, this->GetRelativePathTopBinary());
-
- bool bothInSource =
- PathEqOrSubDir(local_path, this->GetRelativePathTopSource()) &&
- PathEqOrSubDir(remote_path, this->GetRelativePathTopSource());
-
- return bothInBinary || bothInSource;
-}
-
-std::string cmStateDirectory::ConvertToRelPathIfNotContained(
- std::string const& local_path, std::string const& remote_path) const
-{
- if (!this->ContainsBoth(local_path, remote_path)) {
- return remote_path;
- }
- return cmSystemTools::ForceToRelativePath(local_path, remote_path);
-}
-
cmStateDirectory::cmStateDirectory(
cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator iter,
const cmStateSnapshot& snapshot)
@@ -591,6 +477,10 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
output = cmJoin(this->DirectoryState->NormalTargetNames, ";");
return &output;
}
+ if (prop == "IMPORTED_TARGETS"_s) {
+ output = cmJoin(this->DirectoryState->ImportedTargetNames, ";");
+ return &output;
+ }
if (prop == "LISTFILE_STACK") {
std::vector<std::string> listFiles;
@@ -662,3 +552,8 @@ void cmStateDirectory::AddNormalTargetName(std::string const& name)
{
this->DirectoryState->NormalTargetNames.push_back(name);
}
+
+void cmStateDirectory::AddImportedTargetName(std::string const& name)
+{
+ this->DirectoryState->ImportedTargetNames.emplace_back(name);
+}
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index 70c19bc1c..b8abccb81 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -28,17 +28,6 @@ public:
std::string const& GetCurrentBinary() const;
void SetCurrentBinary(std::string const& dir);
- std::string const& GetRelativePathTopSource() const;
- std::string const& GetRelativePathTopBinary() const;
- void SetRelativePathTopSource(const char* dir);
- void SetRelativePathTopBinary(const char* dir);
-
- bool ContainsBoth(std::string const& local_path,
- std::string const& remote_path) const;
-
- std::string ConvertToRelPathIfNotContained(
- std::string const& local_path, std::string const& remote_path) const;
-
cmStringRange GetIncludeDirectoriesEntries() const;
cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const;
void AppendIncludeDirectoriesEntry(std::string const& vec,
@@ -92,11 +81,9 @@ public:
std::vector<std::string> GetPropertyKeys() const;
void AddNormalTargetName(std::string const& name);
+ void AddImportedTargetName(std::string const& name);
private:
- void ComputeRelativePathTopSource();
- void ComputeRelativePathTopBinary();
-
cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator
DirectoryState;
cmStateSnapshot Snapshot_;
diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h
index 489264468..6f475f2ee 100644
--- a/Source/cmStatePrivate.h
+++ b/Source/cmStatePrivate.h
@@ -67,14 +67,6 @@ struct cmStateDetail::BuildsystemDirectoryStateType
std::string Location;
std::string OutputLocation;
- // The top-most directories for relative path conversion. Both the
- // source and destination location of a relative path conversion
- // must be underneath one of these directories (both under source or
- // both under binary) in order for the relative path to be evaluated
- // safely by the build tools.
- std::string RelativePathTopSource;
- std::string RelativePathTopBinary;
-
std::vector<std::string> IncludeDirectories;
std::vector<cmListFileBacktrace> IncludeDirectoryBacktraces;
@@ -91,6 +83,7 @@ struct cmStateDetail::BuildsystemDirectoryStateType
std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
std::vector<std::string> NormalTargetNames;
+ std::vector<std::string> ImportedTargetNames;
std::string ProjectName;
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index 1e20abb25..fbf47ef68 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -16,16 +16,9 @@
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStatePrivate.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
-#if !defined(_WIN32)
-# include <sys/utsname.h>
-#endif
-
-#if defined(__CYGWIN__)
-# include "cmSystemTools.h"
-#endif
-
cmStateSnapshot::cmStateSnapshot(cmState* state)
: State(state)
{
@@ -292,34 +285,26 @@ void InitializeContentFromParent(T& parentContent, T& thisContent,
void cmStateSnapshot::SetDefaultDefinitions()
{
-/* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set.
- With CMake must separate between target and host platform. In most cases
- the tests for WIN32, UNIX and APPLE will be for the target system, so an
- additional set of variables for the host system is required ->
- CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE.
- WIN32, UNIX and APPLE are now set in the platform files in
- Modules/Platforms/.
- To keep cmake scripts (-P) and custom language and compiler modules
- working, these variables are still also set here in this place, but they
- will be reset in CMakeSystemSpecificInformation.cmake before the platform
- files are executed. */
-#if defined(_WIN32)
- this->SetDefinition("WIN32", "1");
- this->SetDefinition("CMAKE_HOST_WIN32", "1");
- this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Windows");
-#else
- this->SetDefinition("UNIX", "1");
- this->SetDefinition("CMAKE_HOST_UNIX", "1");
-
-# if defined(__ANDROID__)
- this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Android");
-# else
- struct utsname uts_name;
- if (uname(&uts_name) >= 0) {
- this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname);
+ /* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set.
+ With CMake must separate between target and host platform. In most cases
+ the tests for WIN32, UNIX and APPLE will be for the target system, so an
+ additional set of variables for the host system is required ->
+ CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE.
+ WIN32, UNIX and APPLE are now set in the platform files in
+ Modules/Platforms/.
+ To keep cmake scripts (-P) and custom language and compiler modules
+ working, these variables are still also set here in this place, but they
+ will be reset in CMakeSystemSpecificInformation.cmake before the platform
+ files are executed. */
+ cm::string_view hostSystemName = cmSystemTools::GetSystemName();
+ this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", hostSystemName);
+ if (hostSystemName == "Windows") {
+ this->SetDefinition("WIN32", "1");
+ this->SetDefinition("CMAKE_HOST_WIN32", "1");
+ } else {
+ this->SetDefinition("UNIX", "1");
+ this->SetDefinition("CMAKE_HOST_UNIX", "1");
}
-# endif
-#endif
#if defined(__CYGWIN__)
std::string legacy;
if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) &&
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 23fc3e0f6..5fa309df3 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -241,7 +241,7 @@ bool RegexMatch(std::vector<std::string> const& args,
status.GetMakefile().ClearMatches();
// Compile the regular expression.
cmsys::RegularExpression re;
- if (!re.compile(regex.c_str())) {
+ if (!re.compile(regex)) {
std::string e =
"sub-command REGEX, mode MATCH failed to compile regex \"" + regex +
"\".";
@@ -283,7 +283,7 @@ bool RegexMatchAll(std::vector<std::string> const& args,
status.GetMakefile().ClearMatches();
// Compile the regular expression.
cmsys::RegularExpression re;
- if (!re.compile(regex.c_str())) {
+ if (!re.compile(regex)) {
std::string e =
"sub-command REGEX, mode MATCHALL failed to compile regex \"" + regex +
"\".";
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index c1ce7ec98..10d2e50a4 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -14,11 +14,13 @@
#include "cmSystemTools.h"
+#include <cm/optional>
#include <cmext/algorithm>
#include <cm3p/uv.h>
#include "cmDuration.h"
+#include "cmMessageMetadata.h"
#include "cmProcessOutput.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
@@ -64,6 +66,7 @@
#include <cstdlib>
#include <cstring>
#include <ctime>
+#include <functional>
#include <iostream>
#include <sstream>
#include <utility>
@@ -86,6 +89,7 @@
# include <unistd.h>
# include <sys/time.h>
+# include <sys/types.h>
#endif
#if defined(_WIN32) && \
@@ -101,6 +105,10 @@
# include <malloc.h> /* for malloc/free on QNX */
#endif
+#if !defined(_WIN32) && !defined(__ANDROID__)
+# include <sys/utsname.h>
+#endif
+
namespace {
cmSystemTools::InterruptCallback s_InterruptCallback;
@@ -258,8 +266,15 @@ void cmSystemTools::Stdout(const std::string& s)
void cmSystemTools::Message(const std::string& m, const char* title)
{
+ cmMessageMetadata md;
+ md.title = title;
+ Message(m, md);
+}
+
+void cmSystemTools::Message(const std::string& m, const cmMessageMetadata& md)
+{
if (s_MessageCallback) {
- s_MessageCallback(m, title);
+ s_MessageCallback(m, md);
} else {
std::cerr << m << std::endl;
}
@@ -951,21 +966,87 @@ void cmSystemTools::InitializeLibUV()
#ifdef _WIN32
namespace {
-bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname)
+bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname,
+ cmSystemTools::Replace replace)
{
// Not only ignore any previous error, but clear any memory of it.
SetLastError(0);
- // Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file.
- return MoveFileExW(oldname.c_str(), newname.c_str(),
- MOVEFILE_REPLACE_EXISTING);
+ DWORD flags = 0;
+ if (replace == cmSystemTools::Replace::Yes) {
+ // Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file.
+ flags = flags | MOVEFILE_REPLACE_EXISTING;
+ }
+
+ return MoveFileExW(oldname.c_str(), newname.c_str(), flags);
}
}
#endif
+bool cmSystemTools::CopySingleFile(const std::string& oldname,
+ const std::string& newname)
+{
+ return cmSystemTools::CopySingleFile(oldname, newname, CopyWhen::Always) ==
+ CopyResult::Success;
+}
+
+cmSystemTools::CopyResult cmSystemTools::CopySingleFile(
+ std::string const& oldname, std::string const& newname, CopyWhen when,
+ std::string* err)
+{
+ switch (when) {
+ case CopyWhen::Always:
+ break;
+ case CopyWhen::OnlyIfDifferent:
+ if (!FilesDiffer(oldname, newname)) {
+ return CopyResult::Success;
+ }
+ break;
+ }
+
+ mode_t perm = 0;
+ cmsys::Status perms = SystemTools::GetPermissions(oldname, perm);
+
+ // If files are the same do not copy
+ if (SystemTools::SameFile(oldname, newname)) {
+ return CopyResult::Success;
+ }
+
+ cmsys::Status status;
+ status = cmsys::SystemTools::CloneFileContent(oldname, newname);
+ if (!status) {
+ // if cloning did not succeed, fall back to blockwise copy
+ status = cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname);
+ }
+ if (!status) {
+ if (err) {
+ *err = status.GetString();
+ }
+ return CopyResult::Failure;
+ }
+ if (perms) {
+ status = SystemTools::SetPermissions(newname, perm);
+ if (!status) {
+ if (err) {
+ *err = status.GetString();
+ }
+ return CopyResult::Failure;
+ }
+ }
+ return CopyResult::Success;
+}
+
bool cmSystemTools::RenameFile(const std::string& oldname,
const std::string& newname)
{
+ return cmSystemTools::RenameFile(oldname, newname, Replace::Yes) ==
+ RenameResult::Success;
+}
+
+cmSystemTools::RenameResult cmSystemTools::RenameFile(
+ std::string const& oldname, std::string const& newname, Replace replace,
+ std::string* err)
+{
#ifdef _WIN32
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
@@ -987,7 +1068,7 @@ bool cmSystemTools::RenameFile(const std::string& oldname,
oldname_wstr, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
DWORD move_last_error = 0;
- while (!cmMoveFile(oldname_wstr, newname_wstr) && --retry.Count) {
+ while (!cmMoveFile(oldname_wstr, newname_wstr, replace) && --retry.Count) {
move_last_error = GetLastError();
// There was no error ==> the operation is not yet complete.
@@ -1003,7 +1084,13 @@ bool cmSystemTools::RenameFile(const std::string& oldname,
// 3) Windows Explorer has an associated directory already opened.
if (move_last_error != ERROR_ACCESS_DENIED &&
move_last_error != ERROR_SHARING_VIOLATION) {
- return false;
+ if (replace == Replace::No && move_last_error == ERROR_ALREADY_EXISTS) {
+ return RenameResult::NoReplace;
+ }
+ if (err) {
+ *err = cmsys::Status::Windows(move_last_error).GetString();
+ }
+ return RenameResult::Failure;
}
DWORD const attrs = GetFileAttributesW(newname_wstr.c_str());
@@ -1027,10 +1114,37 @@ bool cmSystemTools::RenameFile(const std::string& oldname,
save_restore_file_attributes.SetPath(newname_wstr);
}
SetLastError(move_last_error);
- return retry.Count > 0;
+ if (retry.Count > 0) {
+ return RenameResult::Success;
+ }
+ if (replace == Replace::No && GetLastError() == ERROR_ALREADY_EXISTS) {
+ return RenameResult::NoReplace;
+ }
+ if (err) {
+ *err = cmsys::Status::Windows_GetLastError().GetString();
+ }
+ return RenameResult::Failure;
#else
- /* On UNIX we have an OS-provided call to do this atomically. */
- return rename(oldname.c_str(), newname.c_str()) == 0;
+ // On UNIX we have OS-provided calls to create 'newname' atomically.
+ if (replace == Replace::No) {
+ if (link(oldname.c_str(), newname.c_str()) == 0) {
+ return RenameResult::Success;
+ }
+ if (errno == EEXIST) {
+ return RenameResult::NoReplace;
+ }
+ if (err) {
+ *err = cmsys::Status::POSIX_errno().GetString();
+ }
+ return RenameResult::Failure;
+ }
+ if (rename(oldname.c_str(), newname.c_str()) == 0) {
+ return RenameResult::Success;
+ }
+ if (err) {
+ *err = cmsys::Status::POSIX_errno().GetString();
+ }
+ return RenameResult::Failure;
#endif
}
@@ -1387,6 +1501,20 @@ std::string cmSystemTools::ForceToRelativePath(std::string const& local_path,
return relative;
}
+std::string cmSystemTools::RelativeIfUnder(std::string const& top,
+ std::string const& in)
+{
+ std::string out;
+ if (in == top) {
+ out = ".";
+ } else if (cmSystemTools::IsSubDirectory(in, top)) {
+ out = in.substr(top.size() + 1);
+ } else {
+ out = in;
+ }
+ return out;
+}
+
#ifndef CMAKE_BOOTSTRAP
bool cmSystemTools::UnsetEnv(const char* value)
{
@@ -1693,7 +1821,7 @@ bool copy_data(struct archive* ar, struct archive* aw)
return false;
}
}
-# if !defined(__clang__) && !defined(__HP_aCC)
+# if !defined(__clang__) && !defined(__NVCOMPILER) && !defined(__HP_aCC)
return false; /* this should not happen but it quiets some compilers */
# endif
}
@@ -2398,6 +2526,7 @@ std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have,
#endif
#if defined(CMake_USE_ELF_PARSER)
+namespace {
struct cmSystemToolsRPathInfo
{
unsigned long Position;
@@ -2405,15 +2534,15 @@ struct cmSystemToolsRPathInfo
std::string Name;
std::string Value;
};
-#endif
+
+using EmptyCallback = std::function<bool(std::string*, const cmELF&)>;
+using AdjustCallback = std::function<bool(
+ cm::optional<std::string>&, const std::string&, const char*, std::string*)>;
// FIXME: Dispatch if multiple formats are supported.
-#if defined(CMake_USE_ELF_PARSER)
-bool cmSystemTools::ChangeRPath(std::string const& file,
- std::string const& oldRPath,
- std::string const& newRPath,
- bool removeEnvironmentRPath, std::string* emsg,
- bool* changed)
+bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback,
+ const AdjustCallback& adjustCallback, std::string* emsg,
+ bool* changed)
{
if (changed) {
*changed = false;
@@ -2440,17 +2569,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
++se_count;
}
if (se_count == 0) {
- if (newRPath.empty()) {
- // The new rpath is empty and there is no rpath anyway so it is
- // okay.
- return true;
- }
- if (emsg) {
- *emsg =
- cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ",
- elf.GetErrorMessage());
- }
- return false;
+ return emptyCallback(emsg, elf);
}
for (int i = 0; i < se_count; ++i) {
@@ -2460,68 +2579,38 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
continue;
}
- // Make sure the current rpath contains the old rpath.
- std::string::size_type pos =
- cmSystemToolsFindRPath(se[i]->Value, oldRPath);
- if (pos == std::string::npos) {
- // If it contains the new rpath instead then it is okay.
- if (cmSystemToolsFindRPath(se[i]->Value, newRPath) !=
- std::string::npos) {
- remove_rpath = false;
- continue;
- }
- if (emsg) {
- std::ostringstream e;
- /* clang-format off */
- e << "The current " << se_name[i] << " is:\n"
- << " " << se[i]->Value << "\n"
- << "which does not contain:\n"
- << " " << oldRPath << "\n"
- << "as was expected.";
- /* clang-format on */
- *emsg = e.str();
- }
- return false;
- }
-
// Store information about the entry in the file.
rp[rp_count].Position = se[i]->Position;
rp[rp_count].Size = se[i]->Size;
rp[rp_count].Name = se_name[i];
- std::string::size_type prefix_len = pos;
-
- // If oldRPath was at the end of the file's RPath, and newRPath is empty,
- // we should remove the unnecessary ':' at the end.
- if (newRPath.empty() && pos > 0 && se[i]->Value[pos - 1] == ':' &&
- pos + oldRPath.length() == se[i]->Value.length()) {
- prefix_len--;
- }
-
- // Construct the new value which preserves the part of the path
- // not being changed.
- if (!removeEnvironmentRPath) {
- rp[rp_count].Value = se[i]->Value.substr(0, prefix_len);
+ // Adjust the rpath.
+ cm::optional<std::string> outRPath;
+ if (!adjustCallback(outRPath, se[i]->Value, se_name[i], emsg)) {
+ return false;
}
- rp[rp_count].Value += newRPath;
- rp[rp_count].Value += se[i]->Value.substr(pos + oldRPath.length());
- if (!rp[rp_count].Value.empty()) {
- remove_rpath = false;
- }
+ if (outRPath) {
+ if (!outRPath->empty()) {
+ remove_rpath = false;
+ }
- // Make sure there is enough room to store the new rpath and at
- // least one null terminator.
- if (rp[rp_count].Size < rp[rp_count].Value.length() + 1) {
- if (emsg) {
- *emsg = cmStrCat("The replacement path is too long for the ",
- se_name[i], " entry.");
+ // Make sure there is enough room to store the new rpath and at
+ // least one null terminator.
+ if (rp[rp_count].Size < outRPath->length() + 1) {
+ if (emsg) {
+ *emsg = cmStrCat("The replacement path is too long for the ",
+ se_name[i], " entry.");
+ }
+ return false;
}
- return false;
- }
- // This entry is ready for update.
- ++rp_count;
+ // This entry is ready for update.
+ rp[rp_count].Value = std::move(*outRPath);
+ ++rp_count;
+ } else {
+ remove_rpath = false;
+ }
}
}
@@ -2580,6 +2669,99 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
}
return true;
}
+
+std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback(
+ const std::string& newRPath)
+{
+ return [newRPath](std::string* emsg, const cmELF& elf) -> bool {
+ if (newRPath.empty()) {
+ // The new rpath is empty and there is no rpath anyway so it is
+ // okay.
+ return true;
+ }
+ if (emsg) {
+ *emsg =
+ cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ",
+ elf.GetErrorMessage());
+ }
+ return false;
+ };
+};
+}
+
+bool cmSystemTools::ChangeRPath(std::string const& file,
+ std::string const& oldRPath,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath, std::string* emsg,
+ bool* changed)
+{
+ auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath](
+ cm::optional<std::string>& outRPath,
+ const std::string& inRPath, const char* se_name,
+ std::string* emsg2) -> bool {
+ // Make sure the current rpath contains the old rpath.
+ std::string::size_type pos = cmSystemToolsFindRPath(inRPath, oldRPath);
+ if (pos == std::string::npos) {
+ // If it contains the new rpath instead then it is okay.
+ if (cmSystemToolsFindRPath(inRPath, newRPath) != std::string::npos) {
+ return true;
+ }
+ if (emsg2) {
+ std::ostringstream e;
+ /* clang-format off */
+ e << "The current " << se_name << " is:\n"
+ << " " << inRPath << "\n"
+ << "which does not contain:\n"
+ << " " << oldRPath << "\n"
+ << "as was expected.";
+ /* clang-format on */
+ *emsg2 = e.str();
+ }
+ return false;
+ }
+
+ std::string::size_type prefix_len = pos;
+
+ // If oldRPath was at the end of the file's RPath, and newRPath is empty,
+ // we should remove the unnecessary ':' at the end.
+ if (newRPath.empty() && pos > 0 && inRPath[pos - 1] == ':' &&
+ pos + oldRPath.length() == inRPath.length()) {
+ prefix_len--;
+ }
+
+ // Construct the new value which preserves the part of the path
+ // not being changed.
+ outRPath.emplace();
+ if (!removeEnvironmentRPath) {
+ *outRPath += inRPath.substr(0, prefix_len);
+ }
+ *outRPath += newRPath;
+ *outRPath += inRPath.substr(pos + oldRPath.length());
+
+ return true;
+ };
+
+ return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg,
+ changed);
+}
+
+bool cmSystemTools::SetRPath(std::string const& file,
+ std::string const& newRPath, std::string* emsg,
+ bool* changed)
+{
+ auto adjustCallback = [newRPath](cm::optional<std::string>& outRPath,
+ const std::string& inRPath,
+ const char* /*se_name*/, std::string *
+ /*emsg*/) -> bool {
+ if (inRPath != newRPath) {
+ outRPath = newRPath;
+ }
+ return true;
+ };
+
+ return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg,
+ changed);
+}
#elif defined(CMake_USE_XCOFF_PARSER)
bool cmSystemTools::ChangeRPath(std::string const& file,
std::string const& oldRPath,
@@ -2649,6 +2831,13 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
}
return true;
}
+
+bool cmSystemTools::SetRPath(std::string const& /*file*/,
+ std::string const& /*newRPath*/,
+ std::string* /*emsg*/, bool* /*changed*/)
+{
+ return false;
+}
#else
bool cmSystemTools::ChangeRPath(std::string const& /*file*/,
std::string const& /*oldRPath*/,
@@ -2658,6 +2847,13 @@ bool cmSystemTools::ChangeRPath(std::string const& /*file*/,
{
return false;
}
+
+bool cmSystemTools::SetRPath(std::string const& /*file*/,
+ std::string const& /*newRPath*/,
+ std::string* /*emsg*/, bool* /*changed*/)
+{
+ return false;
+}
#endif
bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
@@ -3021,7 +3217,7 @@ bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir)
}
return false;
#else
- return cmSystemTools::RemoveADirectory(dir);
+ return static_cast<bool>(cmSystemTools::RemoveADirectory(dir));
#endif
}
@@ -3054,9 +3250,9 @@ std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes)
return out;
}
-bool cmSystemTools::CreateSymlink(const std::string& origName,
- const std::string& newName,
- std::string* errorMessage)
+cmsys::Status cmSystemTools::CreateSymlink(std::string const& origName,
+ std::string const& newName,
+ std::string* errorMessage)
{
uv_fs_t req;
int flags = 0;
@@ -3067,37 +3263,96 @@ bool cmSystemTools::CreateSymlink(const std::string& origName,
#endif
int err = uv_fs_symlink(nullptr, &req, origName.c_str(), newName.c_str(),
flags, nullptr);
+ cmsys::Status status;
if (err) {
- std::string e =
- "failed to create symbolic link '" + newName + "': " + uv_strerror(err);
+#if defined(_WIN32)
+ status = cmsys::Status::Windows(uv_fs_get_system_error(&req));
+#elif UV_VERSION_MAJOR > 1 || (UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR >= 38)
+ status = cmsys::Status::POSIX(uv_fs_get_system_error(&req));
+#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 false;
}
-
- return true;
+ return status;
}
-bool cmSystemTools::CreateLink(const std::string& origName,
- const std::string& newName,
- std::string* errorMessage)
+cmsys::Status cmSystemTools::CreateLink(std::string const& origName,
+ std::string const& newName,
+ std::string* errorMessage)
{
uv_fs_t req;
int err =
uv_fs_link(nullptr, &req, origName.c_str(), newName.c_str(), nullptr);
+ cmsys::Status status;
if (err) {
+#if defined(_WIN32)
+ status = cmsys::Status::Windows(uv_fs_get_system_error(&req));
+#elif UV_VERSION_MAJOR > 1 || (UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR >= 38)
+ status = cmsys::Status::POSIX(uv_fs_get_system_error(&req));
+#else
+ status = cmsys::Status::POSIX(-err);
+#endif
std::string e =
- "failed to create link '" + newName + "': " + uv_strerror(err);
+ cmStrCat("failed to create link '", newName, "': ", status.GetString());
if (errorMessage) {
*errorMessage = std::move(e);
} else {
cmSystemTools::Error(e);
}
- return false;
}
+ return status;
+}
- return true;
+cm::string_view cmSystemTools::GetSystemName()
+{
+#if defined(_WIN32)
+ return "Windows";
+#elif defined(__ANDROID__)
+ return "Android";
+#else
+ static struct utsname uts_name;
+ static bool initialized = false;
+ static cm::string_view systemName;
+ if (initialized) {
+ return systemName;
+ }
+ if (uname(&uts_name) >= 0) {
+ initialized = true;
+ systemName = uts_name.sysname;
+
+ if (cmIsOff(systemName)) {
+ systemName = "UnknownOS";
+ }
+
+ // fix for BSD/OS, remove the /
+ static const cmsys::RegularExpression bsdOsRegex("BSD.OS");
+ cmsys::RegularExpressionMatch match;
+ if (bsdOsRegex.find(uts_name.sysname, match)) {
+ systemName = "BSDOS";
+ }
+
+ // fix for GNU/kFreeBSD, remove the GNU/
+ if (systemName.find("kFreeBSD") != cm::string_view::npos) {
+ systemName = "kFreeBSD";
+ }
+
+ // fix for CYGWIN and MSYS which have windows version in them
+ if (systemName.find("CYGWIN") != cm::string_view::npos) {
+ systemName = "CYGWIN";
+ }
+
+ if (systemName.find("MSYS") != cm::string_view::npos) {
+ systemName = "MSYS";
+ }
+ return systemName;
+ }
+ return "";
+#endif
}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 5bbbb0c7b..44ccbf7a3 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -12,12 +12,15 @@
#include <cm/string_view>
#include "cmsys/Process.h"
+#include "cmsys/Status.hxx" // IWYU pragma: export
#include "cmsys/SystemTools.hxx" // IWYU pragma: export
#include "cmCryptoHash.h"
#include "cmDuration.h"
#include "cmProcessOutput.h"
+struct cmMessageMetadata;
+
/** \class cmSystemTools
* \brief A collection of useful functions for CMake.
*
@@ -39,7 +42,8 @@ public:
/** Map help document name to file name. */
static std::string HelpFileName(cm::string_view);
- using MessageCallback = std::function<void(const std::string&, const char*)>;
+ using MessageCallback =
+ std::function<void(const std::string&, const cmMessageMetadata&)>;
/**
* Set the function used by GUIs to display error messages
* Function gets passed: message as a const char*,
@@ -56,6 +60,7 @@ public:
* Display a message.
*/
static void Message(const std::string& m, const char* title = nullptr);
+ static void Message(const std::string& m, const cmMessageMetadata& md);
using OutputCallback = std::function<void(std::string const&)>;
@@ -128,10 +133,43 @@ public:
static bool SimpleGlob(const std::string& glob,
std::vector<std::string>& files, int type = 0);
+ enum class CopyWhen
+ {
+ Always,
+ OnlyIfDifferent,
+ };
+ enum class CopyResult
+ {
+ Success,
+ Failure,
+ };
+
+ /** Copy a file. */
+ static bool CopySingleFile(const std::string& oldname,
+ const std::string& newname);
+ static CopyResult CopySingleFile(std::string const& oldname,
+ std::string const& newname, CopyWhen when,
+ std::string* err = nullptr);
+
+ enum class Replace
+ {
+ Yes,
+ No,
+ };
+ enum class RenameResult
+ {
+ Success,
+ NoReplace,
+ Failure,
+ };
+
/** Rename a file or directory within a single disk volume (atomic
if possible). */
static bool RenameFile(const std::string& oldname,
const std::string& newname);
+ static RenameResult RenameFile(std::string const& oldname,
+ std::string const& newname, Replace replace,
+ std::string* err = nullptr);
//! Rename a file if contents are different, delete the source otherwise
static void MoveFileIfDifferent(const std::string& source,
@@ -152,7 +190,7 @@ public:
*
* Output is controlled with outputflag. If outputflag is OUTPUT_NONE, no
* user-viewable output from the program being run will be generated.
- * OUTPUT_MERGE is the legacy behaviour where stdout and stderr are merged
+ * OUTPUT_MERGE is the legacy behavior where stdout and stderr are merged
* into stdout. OUTPUT_FORWARD copies the output to stdout/stderr as
* it was received. OUTPUT_PASSTHROUGH passes through the original handles.
*
@@ -312,6 +350,12 @@ public:
static std::string ForceToRelativePath(std::string const& local_path,
std::string const& remote_path);
+ /**
+ * Express the 'in' path relative to 'top' if it does not start in '../'.
+ */
+ static std::string RelativeIfUnder(std::string const& top,
+ std::string const& in);
+
#ifndef CMAKE_BOOTSTRAP
/** Remove an environment variable */
static bool UnsetEnv(const char* value);
@@ -412,13 +456,17 @@ public:
static bool GuessLibraryInstallName(std::string const& fullPath,
std::string& soname);
- /** Try to set the RPATH in an ELF binary. */
+ /** Try to change the RPATH in an ELF binary. */
static bool ChangeRPath(std::string const& file, std::string const& oldRPath,
std::string const& newRPath,
bool removeEnvironmentRPath,
std::string* emsg = nullptr,
bool* changed = nullptr);
+ /** Try to set the RPATH in an ELF binary. */
+ static bool SetRPath(std::string const& file, std::string const& newRPath,
+ std::string* emsg = nullptr, bool* changed = nullptr);
+
/** Try to remove the RPATH from an ELF binary. */
static bool RemoveRPath(std::string const& file, std::string* emsg = nullptr,
bool* removed = nullptr);
@@ -455,15 +503,18 @@ public:
/** Create a symbolic link if the platform supports it. Returns whether
creation succeeded. */
- static bool CreateSymlink(const std::string& origName,
- const std::string& newName,
- std::string* errorMessage = nullptr);
+ static cmsys::Status CreateSymlink(std::string const& origName,
+ std::string const& newName,
+ std::string* errorMessage = nullptr);
/** Create a hard link if the platform supports it. Returns whether
creation succeeded. */
- static bool CreateLink(const std::string& origName,
- const std::string& newName,
- std::string* errorMessage = nullptr);
+ static cmsys::Status CreateLink(std::string const& origName,
+ std::string const& newName,
+ std::string* errorMessage = nullptr);
+
+ /** Get the system name. */
+ static cm::string_view GetSystemName();
private:
static bool s_ForceUnixPaths;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 91dcd0efc..762270051 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -288,6 +288,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
SETUP_COMMON_LANGUAGE_PROPERTIES(CXX);
SETUP_COMMON_LANGUAGE_PROPERTIES(OBJCXX);
SETUP_COMMON_LANGUAGE_PROPERTIES(CUDA);
+ SETUP_COMMON_LANGUAGE_PROPERTIES(HIP);
initProp("ANDROID_API");
initProp("ANDROID_API_MIN");
@@ -354,15 +355,19 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("C_CPPLINT");
initProp("C_CPPCHECK");
initProp("C_INCLUDE_WHAT_YOU_USE");
+ initProp("C_LINKER_LAUNCHER");
initProp("LINK_WHAT_YOU_USE");
initProp("CXX_CLANG_TIDY");
initProp("CXX_CPPLINT");
initProp("CXX_CPPCHECK");
initProp("CXX_INCLUDE_WHAT_YOU_USE");
+ initProp("CXX_LINKER_LAUNCHER");
initProp("CUDA_SEPARABLE_COMPILATION");
initProp("CUDA_RESOLVE_DEVICE_SYMBOLS");
initProp("CUDA_RUNTIME_LIBRARY");
initProp("CUDA_ARCHITECTURES");
+ initProp("HIP_RUNTIME_LIBRARY");
+ initProp("HIP_ARCHITECTURES");
initProp("VISIBILITY_INLINES_HIDDEN");
initProp("JOB_POOL_COMPILE");
initProp("JOB_POOL_LINK");
@@ -374,7 +379,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("LINK_SEARCH_START_STATIC");
initProp("LINK_SEARCH_END_STATIC");
initProp("OBJC_CLANG_TIDY");
+ initProp("OBJC_LINKER_LAUNCHER");
initProp("OBJCXX_CLANG_TIDY");
+ initProp("OBJCXX_LINKER_LAUNCHER");
initProp("Swift_LANGUAGE_VERSION");
initProp("Swift_MODULE_DIRECTORY");
initProp("VS_JUST_MY_CODE_DEBUGGING");
@@ -929,12 +936,10 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
const char* sigString =
(sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain");
s << "The uses of the " << sigString << " signature are here:\n";
- cmStateDirectory cmDir =
- this->impl->Makefile->GetStateSnapshot().GetDirectory();
for (auto const& cmd : this->impl->TLLCommands) {
if (cmd.first == sig) {
cmListFileContext lfc = cmd.second;
- lfc.FilePath = cmDir.ConvertToRelPathIfNotContained(
+ lfc.FilePath = cmSystemTools::RelativeIfUnder(
this->impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
s << " * " << lfc << '\n';
}
@@ -1166,6 +1171,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
MAKE_STATIC_PROP(C_STANDARD);
MAKE_STATIC_PROP(CXX_STANDARD);
MAKE_STATIC_PROP(CUDA_STANDARD);
+ MAKE_STATIC_PROP(HIP_STANDARD);
MAKE_STATIC_PROP(OBJC_STANDARD);
MAKE_STATIC_PROP(OBJCXX_STANDARD);
MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
@@ -1352,8 +1358,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
this->SetProperty("COMPILE_PDB_NAME", cmToCStr(tmp));
this->AddUtility(reusedFrom, false, this->impl->Makefile);
} else if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
- prop == propCUDA_STANDARD || prop == propOBJC_STANDARD ||
- prop == propOBJCXX_STANDARD) {
+ prop == propCUDA_STANDARD || prop == propHIP_STANDARD ||
+ prop == propOBJC_STANDARD || prop == propOBJCXX_STANDARD) {
if (value) {
this->impl->LanguageStandardProperties[prop] =
BTs<std::string>(value, this->impl->Makefile->GetBacktrace());
@@ -1459,8 +1465,8 @@ void cmTarget::AppendProperty(const std::string& prop,
this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR, prop + " property may not be APPENDed.");
} else if (prop == "C_STANDARD" || prop == "CXX_STANDARD" ||
- prop == "CUDA_STANDARD" || prop == "OBJC_STANDARD" ||
- prop == "OBJCXX_STANDARD") {
+ prop == "CUDA_STANDARD" || prop == "HIP_STANDARD" ||
+ prop == "OBJC_STANDARD" || prop == "OBJCXX_STANDARD") {
this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR, prop + " property may not be appended.");
} else {
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index aecc18e3a..3423b30dc 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -565,7 +565,7 @@ void TLL::AffectsProperty(std::string const& prop)
if (!this->EncodeRemoteReference) {
return;
}
- // Add a wrapper to the expression to tell LookupLinkItems to look up
+ // 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);
diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx
index 78aa4b2df..4032596b8 100644
--- a/Source/cmTransformDepfile.cxx
+++ b/Source/cmTransformDepfile.cxx
@@ -2,6 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTransformDepfile.h"
+#include <algorithm>
+#include <functional>
+#include <memory>
#include <string>
#include <type_traits>
#include <utility>
@@ -13,6 +16,7 @@
#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h"
+#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmSystemTools.h"
@@ -34,10 +38,18 @@ void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename)
}
}
-void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg,
- const cmGccDepfileContent& content)
+void WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout,
+ const cmLocalGenerator& lg,
+ const cmGccDepfileContent& content)
{
- const auto& binDir = lg.GetBinaryDirectory();
+ std::function<std::string(const std::string&)> formatPath =
+ [&lg](const std::string& path) -> std::string {
+ return lg.MaybeRelativeToTopBinDir(path);
+ };
+ if (lg.GetGlobalGenerator()->GetName() == "Xcode") {
+ // full paths must be preserved for Xcode compliance
+ formatPath = [](const std::string& path) -> std::string { return path; };
+ }
for (auto const& dep : content) {
bool first = true;
@@ -46,50 +58,53 @@ void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg,
fout << " \\\n ";
}
first = false;
- WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, rule));
+ WriteFilenameGcc(fout, formatPath(rule));
}
fout << ':';
for (auto const& path : dep.paths) {
fout << " \\\n ";
- WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, path));
+ WriteFilenameGcc(fout, formatPath(path));
}
fout << '\n';
}
-}
-// tlog format : always windows paths on Windows regardless the generator
-std::string ConvertToTLogOutputPath(const std::string& path)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- return cmSystemTools::ConvertToWindowsOutputPath(path);
-#else
- return cmSystemTools::ConvertToOutputPath(path);
-#endif
+ if (format == cmDepfileFormat::MakeDepfile) {
+ // In this case, phony targets must be added for all dependencies
+ fout << "\n";
+ for (auto const& dep : content) {
+ for (auto const& path : dep.paths) {
+ fout << "\n";
+ WriteFilenameGcc(fout, formatPath(path));
+ fout << ":\n";
+ }
+ }
+ }
}
-void WriteVsTlog(cmsys::ofstream& fout, const cmLocalGenerator& lg,
- const cmGccDepfileContent& content)
+void WriteMSBuildAdditionalInputs(cmsys::ofstream& fout,
+ cmLocalGenerator const& lg,
+ cmGccDepfileContent const& content)
{
- const auto& binDir = lg.GetBinaryDirectory();
+ if (content.empty()) {
+ return;
+ }
- for (auto const& dep : content) {
- fout << '^';
- bool first = true;
- for (auto const& rule : dep.rules) {
- if (!first) {
- fout << '|';
- }
- first = false;
- fout << ConvertToTLogOutputPath(
- lg.MaybeConvertToRelativePath(binDir, rule));
- }
- fout << "\r\n";
- for (auto const& path : dep.paths) {
- fout << ConvertToTLogOutputPath(
- lg.MaybeConvertToRelativePath(binDir, path))
- << "\r\n";
+ // Write a UTF-8 BOM so MSBuild knows the encoding when reading the file.
+ static const char utf8bom[] = { char(0xEF), char(0xBB), char(0xBF) };
+ fout.write(utf8bom, sizeof(utf8bom));
+
+ // Write the format expected by MSBuild CustomBuild AdditionalInputs.
+ const char* sep = "";
+ for (std::string path : content.front().paths) {
+ if (!cmSystemTools::FileIsFullPath(path)) {
+ path =
+ cmSystemTools::CollapseFullPath(path, lg.GetCurrentBinaryDirectory());
}
+ std::replace(path.begin(), path.end(), '/', '\\');
+ fout << sep << path;
+ sep = ";";
}
+ fout << "\n";
}
}
@@ -106,16 +121,18 @@ bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg,
content = *std::move(result);
}
+ cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(outfile));
cmsys::ofstream fout(outfile.c_str());
if (!fout) {
return false;
}
switch (format) {
case cmDepfileFormat::GccDepfile:
- WriteGccDepfile(fout, lg, content);
+ case cmDepfileFormat::MakeDepfile:
+ WriteDepfile(format, fout, lg, content);
break;
- case cmDepfileFormat::VsTlog:
- WriteVsTlog(fout, lg, content);
+ case cmDepfileFormat::MSBuildAdditionalInputs:
+ WriteMSBuildAdditionalInputs(fout, lg, content);
break;
}
return true;
diff --git a/Source/cmTransformDepfile.h b/Source/cmTransformDepfile.h
index c43a45f27..379e8bc88 100644
--- a/Source/cmTransformDepfile.h
+++ b/Source/cmTransformDepfile.h
@@ -7,7 +7,8 @@
enum class cmDepfileFormat
{
GccDepfile,
- VsTlog,
+ MakeDepfile,
+ MSBuildAdditionalInputs,
};
class cmLocalGenerator;
diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx
index 8ea19423d..e05b2d526 100644
--- a/Source/cmUVHandlePtr.cxx
+++ b/Source/cmUVHandlePtr.cxx
@@ -128,7 +128,7 @@ template <>
struct uv_handle_deleter<uv_async_t>
{
/***
- * Wile uv_async_send is itself thread-safe, there are
+ * While uv_async_send is itself thread-safe, there are
* no strong guarantees that close hasn't already been
* called on the handle; and that it might be deleted
* as the send call goes through. This mutex guards
diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx
index 9626599a3..969a2c2c1 100644
--- a/Source/cmVSSetupHelper.cxx
+++ b/Source/cmVSSetupHelper.cxx
@@ -258,15 +258,13 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(std::string& vsInstallLocation)
return isInstalled;
}
-bool cmVSSetupAPIHelper::GetVSInstanceVersion(
- unsigned long long& vsInstanceVersion)
+bool cmVSSetupAPIHelper::GetVSInstanceVersion(std::string& vsInstanceVersion)
{
- vsInstanceVersion = 0;
+ vsInstanceVersion.clear();
bool isInstalled = this->EnumerateAndChooseVSInstance();
if (isInstalled) {
- vsInstanceVersion =
- static_cast<unsigned long long>(chosenInstanceInfo.ullVersion);
+ vsInstanceVersion = cmsys::Encoding::ToNarrow(chosenInstanceInfo.Version);
}
return isInstalled;
diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h
index 04ea46db1..61a3ac7f8 100644
--- a/Source/cmVSSetupHelper.h
+++ b/Source/cmVSSetupHelper.h
@@ -88,7 +88,7 @@ struct VSInstanceInfo
std::wstring VSInstallLocation;
std::wstring Version;
std::string VCToolsetVersion;
- ULONGLONG ullVersion = 0;
+ ULONGLONG ullVersion = 0; // A.B.C.D = (A<<48)|(B<<32)|(C<<16)|D
bool IsWin10SDKInstalled = false;
bool IsWin81SDKInstalled = false;
@@ -105,7 +105,7 @@ public:
bool IsVSInstalled();
bool GetVSInstanceInfo(std::string& vsInstallLocation);
- bool GetVSInstanceVersion(unsigned long long& vsInstanceVersion);
+ bool GetVSInstanceVersion(std::string& vsInstanceVersion);
bool GetVCToolsetVersion(std::string& vsToolsetVersion);
bool IsWin10SDKInstalled();
bool IsWin81SDKInstalled();
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 965ac3eee..11a8b1f3e 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -498,7 +498,7 @@ void cmVisualStudio10TargetGenerator::Generate()
cmProp targetFramework =
this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK");
if (targetFramework) {
- if (std::strchr(targetFramework->c_str(), ';') != nullptr) {
+ if (targetFramework->find(';') != std::string::npos) {
e1.Element("TargetFrameworks", *targetFramework);
} else {
e1.Element("TargetFramework", *targetFramework);
@@ -545,7 +545,7 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element(
"CudaToolkitCustomDir",
this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString() +
- "nvcc");
+ this->GlobalGenerator->GetPlatformToolsetCudaNvccSubdirString());
}
}
@@ -654,8 +654,9 @@ void cmVisualStudio10TargetGenerator::Generate()
std::string cudaPath = customDir.empty()
? "$(VCTargetsPath)\\BuildCustomizations\\"
: customDir +
- "CUDAVisualStudioIntegration\\extras\\"
- "visual_studio_integration\\MSBuildExtensions\\";
+ this->GlobalGenerator
+ ->GetPlatformToolsetCudaVSIntegrationSubdirString() +
+ "extras\\visual_studio_integration\\MSBuildExtensions\\";
Elem(e1, "Import")
.Attribute("Project",
std::move(cudaPath) + "CUDA " +
@@ -747,8 +748,9 @@ void cmVisualStudio10TargetGenerator::Generate()
std::string cudaPath = customDir.empty()
? "$(VCTargetsPath)\\BuildCustomizations\\"
: customDir +
- "CUDAVisualStudioIntegration\\extras\\"
- "visual_studio_integration\\MSBuildExtensions\\";
+ this->GlobalGenerator
+ ->GetPlatformToolsetCudaVSIntegrationSubdirString() +
+ "extras\\visual_studio_integration\\MSBuildExtensions\\";
Elem(e1, "Import")
.Attribute("Project",
std::move(cudaPath) + "CUDA " +
@@ -766,6 +768,11 @@ void cmVisualStudio10TargetGenerator::Generate()
Elem(e1, "Import").Attribute("Project", nasmTargets);
}
}
+ if (this->ProjectType == vcxproj && this->HaveCustomCommandDepfile) {
+ std::string depfileTargets =
+ GetCMakeFilePath("Templates/MSBuild/CustomBuildDepFile.targets");
+ Elem(e0, "Import").Attribute("Project", depfileTargets);
+ }
if (this->ProjectType == csproj) {
for (std::string const& c : this->Configurations) {
Elem e1(e0, "PropertyGroup");
@@ -1458,7 +1465,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
e2.SetHasElements();
}
for (std::string const& c : this->Configurations) {
- cmCustomCommandGenerator ccg(command, c, lg);
+ cmCustomCommandGenerator ccg(command, c, lg, true);
std::string comment = lg->ConstructComment(ccg);
comment = cmVS10EscapeComment(comment);
std::string script = lg->ConstructScript(ccg);
@@ -1522,10 +1529,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
std::string name = "CustomCommand_" + c + "_" +
cmSystemTools::ComputeStringMD5(sourcePath);
this->WriteCustomRuleCSharp(e0, c, name, script, additional_inputs.str(),
- outputs.str(), comment);
+ outputs.str(), comment, ccg);
} else {
this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(),
- outputs.str(), comment, symbolic);
+ outputs.str(), comment, ccg, symbolic);
}
}
}
@@ -1533,7 +1540,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
Elem& e2, std::string const& config, std::string const& script,
std::string const& additional_inputs, std::string const& outputs,
- std::string const& comment, bool symbolic)
+ std::string const& comment, cmCustomCommandGenerator const& ccg,
+ bool symbolic)
{
const std::string cond = this->CalcCondition(config);
e2.WritePlatformConfigTag("Message", cond, comment);
@@ -1552,13 +1560,29 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
// outputs is marked SYMBOLIC and not expected to be created.
e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false");
}
+
+ std::string depfile = ccg.GetFullDepfile();
+ if (!depfile.empty()) {
+ this->HaveCustomCommandDepfile = true;
+ std::string internal_depfile = ccg.GetInternalDepfile();
+ ConvertToWindowsSlash(internal_depfile);
+ e2.WritePlatformConfigTag("DepFileAdditionalInputsFile", cond,
+ internal_depfile);
+ }
}
void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
Elem& e0, std::string const& config, std::string const& name,
std::string const& script, std::string const& inputs,
- std::string const& outputs, std::string const& comment)
+ std::string const& outputs, std::string const& comment,
+ cmCustomCommandGenerator const& ccg)
{
+ if (!ccg.GetFullDepfile().empty()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("CSharp target \"", this->GeneratorTarget->GetName(),
+ "\" does not support add_custom_command DEPFILE."));
+ }
this->CSharpCustomCommandNames.insert(name);
Elem e1(e0, "Target");
e1.Attribute("Condition", this->CalcCondition(config));
@@ -2275,6 +2299,20 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
std::back_inserter(exclude_configs));
Elem e2(e1, tool);
+ bool isCSharp = (si.Source->GetLanguage() == "CSharp");
+ if (isCSharp && exclude_configs.size() > 0) {
+ std::stringstream conditions;
+ bool firstConditionSet{ false };
+ for (const auto& ci : include_configs) {
+ if (firstConditionSet) {
+ conditions << " Or ";
+ }
+ conditions << "('$(Configuration)|$(Platform)'=='" +
+ this->Configurations[ci] + "|" + this->Platform + "')";
+ firstConditionSet = true;
+ }
+ e2.Attribute("Condition", conditions.str());
+ }
this->WriteSource(e2, si.Source);
bool useNativeUnityBuild = false;
@@ -2319,7 +2357,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
e2.Element("PrecompiledHeader", "NotUsing");
}
- if (!exclude_configs.empty()) {
+ if (!isCSharp && !exclude_configs.empty()) {
this->WriteExcludeFromBuild(e2, exclude_configs);
}
}
@@ -3340,8 +3378,6 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
// cmLinkLineDeviceComputer
cmComputeLinkInformation& cli = *pcli;
std::vector<std::string> libVec;
- const std::string currentBinDir =
- this->LocalGenerator->GetCurrentBinaryDirectory();
const auto& libs = cli.GetItems();
for (cmComputeLinkInformation::Item const& l : libs) {
@@ -3377,9 +3413,9 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
}
}
- if (l.IsPath) {
- std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
- currentBinDir, l.Value.Value);
+ if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
+ std::string path =
+ this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
ConvertToWindowsSlash(path);
if (!cmVS10IsTargetsFile(l.Value.Value)) {
libVec.push_back(path);
@@ -3930,12 +3966,11 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
cmComputeLinkInformation& cli = *pcli;
using ItemVector = cmComputeLinkInformation::ItemVector;
const ItemVector& libs = cli.GetItems();
- std::string currentBinDir =
- this->LocalGenerator->GetCurrentBinaryDirectory();
for (cmComputeLinkInformation::Item const& l : libs) {
- if (l.IsPath && cmVS10IsTargetsFile(l.Value.Value)) {
- std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
- currentBinDir, l.Value.Value);
+ if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes &&
+ cmVS10IsTargetsFile(l.Value.Value)) {
+ std::string path =
+ this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
ConvertToWindowsSlash(path);
this->AddTargetsFileAndConfigPair(path, config);
}
@@ -3975,8 +4010,6 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
{
using ItemVector = cmComputeLinkInformation::ItemVector;
ItemVector const& libs = cli.GetItems();
- std::string currentBinDir =
- this->LocalGenerator->GetCurrentBinaryDirectory();
for (cmComputeLinkInformation::Item const& l : libs) {
if (l.Target) {
auto managedType = l.Target->GetManagedType(config);
@@ -4018,9 +4051,9 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
}
}
- if (l.IsPath) {
- std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
- currentBinDir, l.Value.Value);
+ if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
+ std::string path =
+ this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
ConvertToWindowsSlash(path);
if (cmVS10IsTargetsFile(l.Value.Value)) {
vsTargetVec.push_back(path);
@@ -4237,11 +4270,10 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
if (dt->IsCSharpOnly() || cmHasLiteralSuffix(path, "csproj")) {
e2.Element("SkipGetTargetFrameworkProperties", "true");
}
-
// Don't reference targets that don't produce any output.
- if (this->Configurations.empty() ||
- dt->GetManagedType(this->Configurations[0]) ==
- cmGeneratorTarget::ManagedType::Undefined) {
+ else if (this->Configurations.empty() ||
+ dt->GetManagedType(this->Configurations[0]) ==
+ cmGeneratorTarget::ManagedType::Undefined) {
e2.Element("ReferenceOutputAssembly", "false");
e2.Element("CopyToOutputDirectory", "Never");
}
@@ -5035,7 +5067,9 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
{
// For out of source files, we first check if a matching source group
// for this file exists, otherwise we check if the path relative to current
- // source- or binary-dir is used within the link and return that
+ // source- or binary-dir is used within the link and return that.
+ // In case of .cs files we can't do that automatically for files in the
+ // binary directory, because this leads to compilation errors.
std::string link;
std::string sourceGroupedFile;
std::string const& fullFileName = source->GetFullPath();
@@ -5057,7 +5091,8 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
link = sourceGroupedFile;
} else if (cmHasPrefix(fullFileName, srcDir)) {
link = fullFileName.substr(srcDir.length() + 1);
- } else if (cmHasPrefix(fullFileName, binDir)) {
+ } else if (!cmHasSuffix(fullFileName, ".cs") &&
+ cmHasPrefix(fullFileName, binDir)) {
link = fullFileName.substr(binDir.length() + 1);
} else if (cmProp l = source->GetProperty("VS_CSHARP_Link")) {
link = *l;
@@ -5080,7 +5115,9 @@ std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
void cmVisualStudio10TargetGenerator::WriteStdOutEncodingUtf8(Elem& e1)
{
- if (this->GlobalGenerator->IsStdOutEncodingSupported()) {
+ if (this->GlobalGenerator->IsUtf8EncodingSupported()) {
+ e1.Element("UseUtf8Encoding", "Always");
+ } else if (this->GlobalGenerator->IsStdOutEncodingSupported()) {
e1.Element("StdOutEncoding", "UTF-8");
}
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 35dbba812..55c5444f1 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -16,6 +16,7 @@
class cmComputeLinkInformation;
class cmCustomCommand;
+class cmCustomCommandGenerator;
class cmGeneratedFileStream;
class cmGlobalVisualStudio10Generator;
class cmLocalVisualStudio10Generator;
@@ -143,13 +144,15 @@ private:
std::string const& script,
std::string const& additional_inputs,
std::string const& outputs,
- std::string const& comment, bool symbolic);
+ std::string const& comment,
+ cmCustomCommandGenerator const& ccg, bool symbolic);
void WriteCustomRuleCSharp(Elem& e0, std::string const& config,
std::string const& commandName,
std::string const& script,
std::string const& inputs,
std::string const& outputs,
- std::string const& comment);
+ std::string const& comment,
+ cmCustomCommandGenerator const& ccg);
void WriteCustomCommands(Elem& e0);
void WriteCustomCommand(Elem& e0, cmSourceFile const* sf);
void WriteGroups();
@@ -216,6 +219,7 @@ private:
bool Managed;
bool NsightTegra;
bool Android;
+ bool HaveCustomCommandDepfile = false;
unsigned int NsightTegraVersion[4];
bool TargetCompileAsWinRT;
std::set<std::string> IPOEnabledConfigurations;
diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx
deleted file mode 100644
index 7fc33e63e..000000000
--- a/Source/cmVisualStudio10ToolsetOptions.cxx
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmVisualStudio10ToolsetOptions.h"
-
-#include "cmAlgorithms.h"
-#include "cmIDEFlagTable.h"
-#include "cmVisualStudioGeneratorOptions.h"
-
-std::string cmVisualStudio10ToolsetOptions::GetClFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if (toolset == "v142") {
- return "v142";
- } else if (toolset == "v141") {
- return "v141";
- } else if (useToolset == "v140") {
- return "v140";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetCSharpFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if (useToolset == "v142") {
- return "v142";
- } else if (useToolset == "v141") {
- return "v141";
- } else if (useToolset == "v140") {
- return "v140";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetRcFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if ((useToolset == "v140") || (useToolset == "v141") ||
- (useToolset == "v142")) {
- return "v14";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetLibFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if ((useToolset == "v140") || (useToolset == "v141") ||
- (useToolset == "v142")) {
- return "v14";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetLinkFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if (useToolset == "v142") {
- return "v142";
- } else if (useToolset == "v141") {
- return "v141";
- } else if (useToolset == "v140") {
- return "v140";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetMasmFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if ((useToolset == "v140") || (useToolset == "v141") ||
- (useToolset == "v142")) {
- return "v14";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetToolsetName(
- std::string const& name, std::string const& toolset) const
-{
- static_cast<void>(name);
- std::size_t length = toolset.length();
-
- if (cmHasLiteralSuffix(toolset, "_xp")) {
- length -= 3;
- }
-
- return toolset.substr(0, length);
-}
diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h
deleted file mode 100644
index 85cc2b6b2..000000000
--- a/Source/cmVisualStudio10ToolsetOptions.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 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>
-
-/** \class cmVisualStudio10ToolsetOptions
- * \brief Retrieves toolset options for MSBuild.
- *
- * cmVisualStudio10ToolsetOptions manages toolsets within MSBuild
- */
-class cmVisualStudio10ToolsetOptions
-{
-public:
- std::string GetClFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetCSharpFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetRcFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetLibFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetLinkFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetMasmFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetToolsetName(std::string const& name,
- std::string const& toolset) const;
-};
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 937b4ce4a..058ffb495 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -75,6 +75,7 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
case cmGlobalVisualStudioGenerator::VS14:
case cmGlobalVisualStudioGenerator::VS15:
case cmGlobalVisualStudioGenerator::VS16:
+ case cmGlobalVisualStudioGenerator::VS17:
// by default VS puts <ExceptionHandling></ExceptionHandling> empty
// for a project, to make our projects look the same put a new line
// and space over for the closing </ExceptionHandling> as the default
@@ -418,7 +419,9 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
}
std::ostringstream oss;
- const char* sep = "";
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ oss << "%(" << tag << ")";
+ }
std::vector<std::string>::const_iterator de =
cmRemoveDuplicates(this->Defines);
for (std::string const& di : cmMakeRange(this->Defines.cbegin(), de)) {
@@ -437,11 +440,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
}
}
// Store the flag in the project file.
- oss << sep << define;
- sep = ";";
- }
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- oss << ";%(" << tag << ")";
+ oss << ';' << define;
}
this->OutputFlag(fout, indent, tag, oss.str());
diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx
index 5700b1cc7..12fae1278 100644
--- a/Source/cmWorkingDirectory.cxx
+++ b/Source/cmWorkingDirectory.cxx
@@ -19,7 +19,7 @@ cmWorkingDirectory::~cmWorkingDirectory()
bool cmWorkingDirectory::SetDirectory(std::string const& newdir)
{
- if (cmSystemTools::ChangeDirectory(newdir) == 0) {
+ if (cmSystemTools::ChangeDirectory(newdir)) {
this->ResultCode = 0;
return true;
}
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
index 55e941d94..e4329afc6 100644
--- a/Source/cmXCodeScheme.cxx
+++ b/Source/cmXCodeScheme.cxx
@@ -324,7 +324,7 @@ bool cmXCodeScheme::WriteLaunchActionBooleanAttribute(
bool defaultValue)
{
cmProp property = Target->GetTarget()->GetProperty(varName);
- bool isOn = (property == nullptr && defaultValue) || cmIsOn(property);
+ bool isOn = (!property && defaultValue) || cmIsOn(property);
if (isOn) {
xout.Attribute(attrName.c_str(), "YES");
diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx
index 15f83e0f7..216d3f017 100644
--- a/Source/cm_codecvt.cxx
+++ b/Source/cm_codecvt.cxx
@@ -31,6 +31,7 @@ codecvt::codecvt(Encoding e)
// We don't know which ANSI encoding to use for other platforms than
// Windows so we don't do any conversion there
case codecvt::UTF8:
+ case codecvt::UTF8_WITH_BOM:
// Assume internal encoding is UTF-8
case codecvt::None:
// No encoding
diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx
index 1860211a1..b73204f2a 100644
--- a/Source/cm_codecvt.hxx
+++ b/Source/cm_codecvt.hxx
@@ -14,6 +14,7 @@ public:
{
None,
UTF8,
+ UTF8_WITH_BOM,
ANSI
};
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index db8600fc7..73f5ad5b8 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -28,6 +28,7 @@
#include "cm_sys_stat.h"
+#include "cmCMakePath.h"
#include "cmCMakePresetsFile.h"
#include "cmCommandLineArgument.h"
#include "cmCommands.h"
@@ -156,7 +157,8 @@ static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
#endif
cmake::cmake(Role role, cmState::Mode mode)
- : FileTimeCache(cm::make_unique<cmFileTimeCache>())
+ : CMakeWorkingDirectory(cmSystemTools::GetCurrentWorkingDirectory())
+ , FileTimeCache(cm::make_unique<cmFileTimeCache>())
#ifndef CMAKE_BOOTSTRAP
, VariableWatch(cm::make_unique<cmVariableWatch>())
#endif
@@ -208,14 +210,15 @@ cmake::cmake(Role role, cmState::Mode mode)
};
// The "c" extension MUST precede the "C" extension.
- setupExts(
- this->CLikeSourceFileExtensions,
- { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "mpp", "m", "M", "mm" });
+ setupExts(this->CLikeSourceFileExtensions,
+ { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "mpp", "m", "M",
+ "mm", "ixx", "cppm" });
setupExts(this->HeaderFileExtensions,
{ "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" });
setupExts(this->CudaFileExtensions, { "cu" });
setupExts(this->FortranFileExtensions,
{ "f", "F", "for", "f77", "f90", "f95", "f03" });
+ setupExts(this->HipFileExtensions, { "hip" });
setupExts(this->ISPCFileExtensions, { "ispc" });
}
}
@@ -258,6 +261,13 @@ Json::Value cmake::ReportCapabilitiesJson() const
gen["name"] = gi.name;
gen["toolsetSupport"] = gi.supportsToolset;
gen["platformSupport"] = gi.supportsPlatform;
+ if (!gi.supportedPlatforms.empty()) {
+ Json::Value supportedPlatforms = Json::arrayValue;
+ for (std::string const& platform : gi.supportedPlatforms) {
+ supportedPlatforms.append(platform);
+ }
+ gen["supportedPlatforms"] = std::move(supportedPlatforms);
+ }
gen["extraGenerators"] = Json::arrayValue;
generatorMap[gi.name] = gen;
} else {
@@ -484,7 +494,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
auto ScriptLambda = [&](std::string const& path, cmake* state) -> bool {
// Register fake project commands that hint misuse in script mode.
GetProjectCommandsInScriptMode(state->GetState());
- // Documented behaviour of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be
+ // Documented behavior of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be
// set to $PWD for -P mode.
state->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
state->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
@@ -493,26 +503,61 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
return true;
};
+ auto PrefixLambda = [&](std::string const& path, cmake* state) -> bool {
+ const std::string var = "CMAKE_INSTALL_PREFIX";
+ cmStateEnums::CacheEntryType type = cmStateEnums::PATH;
+ cmCMakePath absolutePath(path);
+ if (absolutePath.IsAbsolute()) {
+#ifndef CMAKE_BOOTSTRAP
+ state->UnprocessedPresetVariables.erase(var);
+#endif
+ state->ProcessCacheArg(var, path, type);
+ return true;
+ }
+ cmSystemTools::Error("Absolute paths are required for --install-prefix");
+ return false;
+ };
+
+ auto ToolchainLambda = [&](std::string const& path, cmake* state) -> bool {
+ const std::string var = "CMAKE_TOOLCHAIN_FILE";
+ cmStateEnums::CacheEntryType type = cmStateEnums::FILEPATH;
+#ifndef CMAKE_BOOTSTRAP
+ state->UnprocessedPresetVariables.erase(var);
+#endif
+ state->ProcessCacheArg(var, path, type);
+ return true;
+ };
+
std::vector<CommandArgument> arguments = {
CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
- CommandArgument::Values::One, DefineLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, DefineLambda },
CommandArgument{ "-W", "-W must be followed with [no-]<name>.",
- CommandArgument::Values::One, WarningLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, WarningLambda },
CommandArgument{ "-U", "-U must be followed with VAR.",
- CommandArgument::Values::One, UnSetLambda },
- CommandArgument{ "-C", "-C must be followed by a file name.",
CommandArgument::Values::One,
- [&](std::string const& value, cmake* state) -> bool {
- cmSystemTools::Stdout("loading initial cache file " +
- value + "\n");
- // Resolve script path specified on command line
- // relative to $PWD.
- auto path = cmSystemTools::CollapseFullPath(value);
- state->ReadListFile(args, path);
- return true;
- } },
+ CommandArgument::RequiresSeparator::No, UnSetLambda },
+ CommandArgument{
+ "-C", "-C must be followed by a file name.",
+ CommandArgument::Values::One, CommandArgument::RequiresSeparator::No,
+ [&](std::string const& value, cmake* state) -> bool {
+ cmSystemTools::Stdout("loading initial cache file " + value + "\n");
+ // Resolve script path specified on command line
+ // relative to $PWD.
+ auto path = cmSystemTools::CollapseFullPath(value);
+ state->ReadListFile(args, path);
+ return true;
+ } },
+
CommandArgument{ "-P", "-P must be followed by a file name.",
- CommandArgument::Values::One, ScriptLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, ScriptLambda },
+ CommandArgument{ "--toolchain", "No file specified for --toolchain",
+ CommandArgument::Values::One, ToolchainLambda },
+ CommandArgument{ "--install-prefix",
+ "No install directory specified for --install-prefix",
+ CommandArgument::Values::One, PrefixLambda },
CommandArgument{ "--find-package", CommandArgument::Values::Zero,
[&](std::string const&, cmake*) -> bool {
findPackageMode = true;
@@ -649,7 +694,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
this->GlobalGenerator->CreateGenerationObjects();
const auto& lg = this->GlobalGenerator->LocalGenerators[0];
std::string includeFlags =
- lg->GetIncludeFlags(includeDirs, nullptr, language);
+ lg->GetIncludeFlags(includeDirs, nullptr, language, std::string());
std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS");
printf("%s %s\n", includeFlags.c_str(), definitions.c_str());
@@ -790,31 +835,49 @@ void cmake::SetArgs(const std::vector<std::string>& args)
std::vector<CommandArgument> arguments = {
CommandArgument{ "-S", "No source directory specified for -S",
- CommandArgument::Values::One, SourceArgLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, SourceArgLambda },
CommandArgument{ "-H", "No source directory specified for -H",
- CommandArgument::Values::One, SourceArgLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, SourceArgLambda },
CommandArgument{ "-O", CommandArgument::Values::Zero,
IgnoreAndTrueLambda },
CommandArgument{ "-B", "No build directory specified for -B",
- CommandArgument::Values::One, BuildArgLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, BuildArgLambda },
CommandArgument{ "-P", "-P must be followed by a file name.",
CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
[&](std::string const&, cmake*) -> bool {
scriptMode = true;
return true;
} },
CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
+ IgnoreAndTrueLambda },
CommandArgument{ "-C", "-C must be followed by a file name.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
- CommandArgument{ "-U", "-U must be followed with VAR.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
+ IgnoreAndTrueLambda },
+ CommandArgument{
+ "-U", "-U must be followed with VAR.", CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, IgnoreAndTrueLambda },
CommandArgument{ "-W", "-W must be followed with [no-]<name>.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
+ IgnoreAndTrueLambda },
CommandArgument{ "-A", "No platform specified for -A",
- CommandArgument::Values::One, PlatformLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, PlatformLambda },
CommandArgument{ "-T", "No toolset specified for -T",
- CommandArgument::Values::One, ToolsetLamda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, ToolsetLamda },
+ CommandArgument{ "--toolchain", "No file specified for --toolchain",
+ CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument{ "--install-prefix",
+ "No install directory specified for --install-prefix",
+ CommandArgument::Values::One, IgnoreAndTrueLambda },
CommandArgument{ "--check-build-system", CommandArgument::Values::Two,
[](std::string const& value, cmake* state) -> bool {
@@ -1034,6 +1097,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
bool badGeneratorName = false;
CommandArgument generatorCommand(
"-G", "No generator specified for -G", CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
[&](std::string const& value, cmake* state) -> bool {
bool valid = state->CreateAndSetGlobalGenerator(value, true);
badGeneratorName = !valid;
@@ -1194,11 +1258,17 @@ void cmake::SetArgs(const std::vector<std::string>& args)
"\": Invalid macro expansion"));
return;
}
+ if (!expandedPreset->ConditionResult) {
+ cmSystemTools::Error(cmStrCat("Could not use disabled preset \"",
+ preset->second.Unexpanded.Name, "\""));
+ return;
+ }
- if (!this->State->IsCacheLoaded() && !haveBArg) {
+ if (!this->State->IsCacheLoaded() && !haveBArg &&
+ !expandedPreset->BinaryDir.empty()) {
this->SetHomeOutputDirectory(expandedPreset->BinaryDir);
}
- if (!this->GlobalGenerator) {
+ if (!this->GlobalGenerator && !expandedPreset->Generator.empty()) {
if (!this->CreateAndSetGlobalGenerator(expandedPreset->Generator,
false)) {
return;
@@ -1207,6 +1277,19 @@ void cmake::SetArgs(const std::vector<std::string>& args)
this->UnprocessedPresetVariables = expandedPreset->CacheVariables;
this->UnprocessedPresetEnvironment = expandedPreset->Environment;
+ if (!expandedPreset->InstallDir.empty() &&
+ !this->State->GetInitializedCacheValue("CMAKE_INSTALL_PREFIX")) {
+ this->UnprocessedPresetVariables["CMAKE_INSTALL_PREFIX"] = {
+ "PATH", expandedPreset->InstallDir
+ };
+ }
+ if (!expandedPreset->ToolchainFile.empty() &&
+ !this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE")) {
+ this->UnprocessedPresetVariables["CMAKE_TOOLCHAIN_FILE"] = {
+ "FILEPATH", expandedPreset->ToolchainFile
+ };
+ }
+
if (!expandedPreset->ArchitectureStrategy ||
expandedPreset->ArchitectureStrategy ==
cmCMakePresetsFile::ArchToolsetStrategy::Set) {
@@ -1604,6 +1687,9 @@ void cmake::PrintPresetList(const cmCMakePresetsFile& file) const
this->GetRegisteredGenerators(generators, false);
auto filter =
[&generators](const cmCMakePresetsFile::ConfigurePreset& preset) -> bool {
+ if (preset.Generator.empty()) {
+ return true;
+ }
auto condition = [&preset](const GeneratorInfo& info) -> bool {
return info.name == preset.Generator;
};
@@ -1669,17 +1755,20 @@ void cmake::SetGlobalGenerator(std::unique_ptr<cmGlobalGenerator> gg)
}
if (this->GlobalGenerator) {
// restore the original environment variables CXX and CC
- // Restore CC
std::string env = "CC=";
if (!this->CCEnvironment.empty()) {
env += this->CCEnvironment;
+ cmSystemTools::PutEnv(env);
+ } else {
+ cmSystemTools::UnPutEnv(env);
}
- cmSystemTools::PutEnv(env);
env = "CXX=";
if (!this->CXXEnvironment.empty()) {
env += this->CXXEnvironment;
+ cmSystemTools::PutEnv(env);
+ } else {
+ cmSystemTools::UnPutEnv(env);
}
- cmSystemTools::PutEnv(env);
}
// set the new
@@ -1955,6 +2044,16 @@ int cmake::ActualConfigure()
this->GlobalGenerator->GetExtraGeneratorName().c_str(),
"Name of external makefile project generator.",
cmStateEnums::INTERNAL);
+
+ if (!this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE")) {
+ std::string envToolchain;
+ if (cmSystemTools::GetEnv("CMAKE_TOOLCHAIN_FILE", envToolchain) &&
+ !envToolchain.empty()) {
+ this->AddCacheEntry("CMAKE_TOOLCHAIN_FILE", envToolchain.c_str(),
+ "The CMake toolchain file",
+ cmStateEnums::FILEPATH);
+ }
+ }
}
if (cmProp instance =
@@ -2105,7 +2204,9 @@ std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator()
"\\Setup\\VC;ProductDir", //
";InstallDir" //
};
- if (cmVSSetupAPIHelper(16).IsVSInstalled()) {
+ if (cmVSSetupAPIHelper(17).IsVSInstalled()) {
+ found = "Visual Studio 17 2022";
+ } else if (cmVSSetupAPIHelper(16).IsVSInstalled()) {
found = "Visual Studio 16 2019";
} else if (cmVSSetupAPIHelper(15).IsVSInstalled()) {
found = "Visual Studio 15 2017";
@@ -2367,6 +2468,8 @@ std::vector<std::string> cmake::GetAllExtensions() const
// cuda extensions are also in SourceFileExtensions so we ignore it here
allExt.insert(allExt.end(), this->FortranFileExtensions.ordered.begin(),
this->FortranFileExtensions.ordered.end());
+ allExt.insert(allExt.end(), this->HipFileExtensions.ordered.begin(),
+ this->HipFileExtensions.ordered.end());
allExt.insert(allExt.end(), this->ISPCFileExtensions.ordered.begin(),
this->ISPCFileExtensions.ordered.end());
return allExt;
@@ -2408,6 +2511,8 @@ void cmake::AddDefaultGenerators()
#if defined(_WIN32) && !defined(__CYGWIN__)
# if !defined(CMAKE_BOOT_MINGW)
this->Generators.push_back(
+ cmGlobalVisualStudioVersionedGenerator::NewFactory17());
+ this->Generators.push_back(
cmGlobalVisualStudioVersionedGenerator::NewFactory16());
this->Generators.push_back(
cmGlobalVisualStudioVersionedGenerator::NewFactory15());
@@ -3023,12 +3128,16 @@ static bool cmakeCheckStampFile(const std::string& stampName)
cmsys::ofstream stamp(stampTemp.c_str());
stamp << "# CMake generation timestamp file for this directory.\n";
}
- if (cmSystemTools::RenameFile(stampTemp, stampName)) {
+ std::string err;
+ if (cmSystemTools::RenameFile(stampTemp, stampName,
+ cmSystemTools::Replace::Yes, &err) ==
+ cmSystemTools::RenameResult::Success) {
// CMake does not need to re-run because the stamp file is up-to-date.
return true;
}
cmSystemTools::RemoveFile(stampTemp);
- cmSystemTools::Error("Cannot restore timestamp " + stampName);
+ cmSystemTools::Error(
+ cmStrCat("Cannot restore timestamp \"", stampName, "\": ", err));
return false;
}
@@ -3133,6 +3242,14 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
return 1;
}
+ if (!expandedPreset->ConditionResult) {
+ cmSystemTools::Error(cmStrCat("Cannot use disabled build preset in ",
+ this->GetHomeDirectory(), ": \"",
+ presetName, '"'));
+ settingsFile.PrintBuildPresetList();
+ return 1;
+ }
+
auto configurePresetPair =
settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset);
if (configurePresetPair == settingsFile.ConfigurePresets.end()) {
@@ -3159,7 +3276,9 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
return 1;
}
- dir = expandedConfigurePreset->BinaryDir;
+ if (!expandedConfigurePreset->BinaryDir.empty()) {
+ dir = expandedConfigurePreset->BinaryDir;
+ }
this->UnprocessedPresetEnvironment = expandedPreset->Environment;
this->ProcessPresetEnvironment();
diff --git a/Source/cmake.h b/Source/cmake.h
index 82e028c31..5a2a88fac 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -194,6 +194,14 @@ public:
//@}
/**
+ * Working directory at CMake launch
+ */
+ std::string const& GetCMakeWorkingDirectory() const
+ {
+ return this->CMakeWorkingDirectory;
+ }
+
+ /**
* Handle a command line invocation of cmake.
*/
int Run(const std::vector<std::string>& args)
@@ -289,7 +297,7 @@ public:
return this->CLikeSourceFileExtensions.Test(ext) ||
this->CudaFileExtensions.Test(ext) ||
this->FortranFileExtensions.Test(ext) ||
- this->ISPCFileExtensions.Test(ext);
+ this->HipFileExtensions.Test(ext) || this->ISPCFileExtensions.Test(ext);
}
bool IsACLikeSourceExtension(cm::string_view ext) const
@@ -628,6 +636,7 @@ protected:
void GenerateGraphViz(const std::string& fileName) const;
private:
+ std::string CMakeWorkingDirectory;
ProgressCallbackType ProgressCallback;
WorkingMode CurrentWorkingMode = NORMAL_MODE;
bool DebugOutput = false;
@@ -653,6 +662,7 @@ private:
FileExtensions CudaFileExtensions;
FileExtensions ISPCFileExtensions;
FileExtensions FortranFileExtensions;
+ FileExtensions HipFileExtensions;
bool ClearBuildSystem = false;
bool DebugTryCompile = false;
bool RegenerateDuringBuild = false;
@@ -712,6 +722,10 @@ private:
"Specify toolset name if supported by generator." }, \
{ "-A <platform-name>", \
"Specify platform name if supported by generator." }, \
+ { "--toolchain <file>", \
+ "Specify toolchain file [CMAKE_TOOLCHAIN_FILE]." }, \
+ { "--install-prefix <directory>", \
+ "Specify install directory [CMAKE_INSTALL_PREFIX]." }, \
{ "-Wdev", "Enable developer warnings." }, \
{ "-Wno-dev", "Suppress developer warnings." }, \
{ "-Werror=dev", "Make developer warnings errors." }, \
@@ -739,6 +753,8 @@ private:
F(c_std_90) \
F(c_std_99) \
F(c_std_11) \
+ F(c_std_17) \
+ F(c_std_23) \
FOR_EACH_C90_FEATURE(F) \
FOR_EACH_C99_FEATURE(F) \
FOR_EACH_C11_FEATURE(F)
@@ -823,3 +839,11 @@ private:
F(cuda_std_17) \
F(cuda_std_20) \
F(cuda_std_23)
+
+#define FOR_EACH_HIP_FEATURE(F) \
+ F(hip_std_98) \
+ F(hip_std_11) \
+ F(hip_std_14) \
+ F(hip_std_17) \
+ F(hip_std_20) \
+ F(hip_std_23)
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index ad648186b..1725375d9 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -6,6 +6,7 @@
#include <algorithm>
#include <cassert>
#include <climits>
+#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
@@ -23,6 +24,7 @@
#include "cmDocumentationEntry.h" // IWYU pragma: keep
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageMetadata.h"
#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
@@ -37,6 +39,7 @@
#endif
#include "cmsys/Encoding.hxx"
+#include "cmsys/Terminal.h"
namespace {
#ifndef CMAKE_BOOTSTRAP
@@ -147,10 +150,12 @@ std::string cmakemainGetStack(cmake* cm)
return msg;
}
-void cmakemainMessageCallback(const std::string& m, const char* /*unused*/,
- cmake* cm)
+void cmakemainMessageCallback(const std::string& m,
+ const cmMessageMetadata& md, cmake* cm)
{
- std::cerr << m << cmakemainGetStack(cm) << std::endl;
+ cmsysTerminal_cfprintf(md.desiredColor, stderr, "%s", m.c_str());
+ fflush(stderr); // stderr is buffered in some cases.
+ std::cerr << cmakemainGetStack(cm) << "\n";
}
void cmakemainProgressCallback(const std::string& m, float prog, cmake* cm)
@@ -271,6 +276,7 @@ int do_cmake(int ac, char const* const* av)
} },
CommandArgument{ "-P", "No script specified for argument -P",
CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
[&](std::string const& value) -> bool {
workingMode = cmake::SCRIPT_MODE;
parsedArgs.emplace_back("-P");
@@ -342,8 +348,8 @@ int do_cmake(int ac, char const* const* av)
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cmSystemTools::SetMessageCallback(
- [&cm](const std::string& msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
+ [&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);
@@ -476,9 +482,10 @@ int do_build(int ac, char const* const* av)
listPresets = true;
return true;
} },
- CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, jLambda },
+ CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne,
+ CommandArgument::RequiresSeparator::No, jLambda },
CommandArgument{ "--parallel", CommandArgument::Values::ZeroOrOne,
- parallelLambda },
+ CommandArgument::RequiresSeparator::No, parallelLambda },
CommandArgument{ "-t", CommandArgument::Values::OneOrMore, targetLambda },
CommandArgument{ "--target", CommandArgument::Values::OneOrMore,
targetLambda },
@@ -593,7 +600,10 @@ int do_build(int ac, char const* const* av)
if (dir.empty() && presetName.empty() && !listPresets) {
/* clang-format off */
std::cerr <<
- "Usage: cmake --build [<dir> | --preset <preset>] [options] [-- [native-options]]\n"
+ "Usage: cmake --build <dir> "
+ " [options] [-- [native-options]]\n"
+ " cmake --build --preset <preset>"
+ " [options] [-- [native-options]]\n"
"Options:\n"
" <dir> = Project binary directory to be built.\n"
" --preset <preset>, --preset=<preset>\n"
@@ -624,8 +634,8 @@ int do_build(int ac, char const* const* av)
cmake cm(cmake::RoleInternal, cmState::Project);
cmSystemTools::SetMessageCallback(
- [&cm](const std::string& msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
+ [&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);
@@ -857,8 +867,8 @@ int do_install(int ac, char const* const* av)
cmake cm(cmake::RoleScript, cmState::Script);
cmSystemTools::SetMessageCallback(
- [&cm](const std::string& msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
+ [&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);
@@ -938,8 +948,8 @@ int do_open(int ac, char const* const* av)
cmake cm(cmake::RoleInternal, cmState::Unknown);
cmSystemTools::SetMessageCallback(
- [&cm](const std::string& msg, const char* title) {
- cmakemainMessageCallback(msg, title, &cm);
+ [&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);
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 6713cc358..1f4c0b805 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -74,7 +74,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd);
namespace {
-void CMakeCommandUsage(const char* program)
+void CMakeCommandUsage(std::string const& program)
{
std::ostringstream errorStream;
@@ -704,7 +704,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
} else if (args[2] == "--ignore-eol") {
filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]);
} else {
- CMakeCommandUsage(args[0].c_str());
+ CMakeCommandUsage(args[0]);
return 2;
}
@@ -1085,7 +1085,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
std::string const& directory = args[2];
if (!cmSystemTools::FileExists(directory)) {
cmSystemTools::Error("Directory does not exist for chdir command: " +
- args[2]);
+ directory);
return 1;
}
@@ -1152,7 +1152,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
<< "\n";
return 1;
}
- if (!cmSystemTools::CreateSymlink(args[2], args[3])) {
+ if (!cmSystemTools::CreateSymlink(args[2], destinationFileName)) {
return 1;
}
return 0;
@@ -1161,12 +1161,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
// Command to create a hard link. Fails on platforms not
// supporting them.
if (args[1] == "create_hardlink" && args.size() == 4) {
- const char* SouceFileName = args[2].c_str();
- const char* destinationFileName = args[3].c_str();
+ std::string const& sourceFileName = args[2];
+ std::string const& destinationFileName = args[3];
- if (!cmSystemTools::FileExists(SouceFileName)) {
+ if (!cmSystemTools::FileExists(sourceFileName)) {
std::cerr << "failed to create hard link because source path '"
- << SouceFileName << "' does not exist \n";
+ << sourceFileName << "' does not exist \n";
return 1;
}
@@ -1180,7 +1180,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
return 1;
}
- if (!cmSystemTools::CreateLink(args[2], args[3])) {
+ if (!cmSystemTools::CreateLink(sourceFileName, destinationFileName)) {
return 1;
}
return 0;
@@ -1270,11 +1270,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
snapshot.GetDirectory().SetCurrentBinary(startOutDir);
snapshot.GetDirectory().SetCurrentSource(startDir);
- snapshot.GetDirectory().SetRelativePathTopSource(homeDir.c_str());
- snapshot.GetDirectory().SetRelativePathTopBinary(homeOutDir.c_str());
cmMakefile mf(cm.GetGlobalGenerator(), snapshot);
auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf);
+ // FIXME: With advanced add_subdirectory usage, these are
+ // not necessarily the same as the generator originally used.
+ // We should pass all these directories through an info file.
+ lgd->SetRelativePathTopSource(homeDir);
+ lgd->SetRelativePathTopBinary(homeOutDir);
+
// Actually scan dependencies.
return lgd->UpdateDependencies(depInfo, verbose, color) ? 0 : 2;
}
@@ -1525,8 +1529,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
auto format = cmDepfileFormat::GccDepfile;
if (args[3] == "gccdepfile") {
format = cmDepfileFormat::GccDepfile;
- } else if (args[3] == "vstlog") {
- format = cmDepfileFormat::VsTlog;
+ } else if (args[3] == "makedepfile") {
+ format = cmDepfileFormat::MakeDepfile;
+ } else if (args[3] == "MSBuildAdditionalInputs") {
+ format = cmDepfileFormat::MSBuildAdditionalInputs;
} else {
return 1;
}
@@ -1549,18 +1555,22 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
snapshot.GetDirectory().SetCurrentBinary(startOutDir);
snapshot.GetDirectory().SetCurrentSource(startDir);
- snapshot.GetDirectory().SetRelativePathTopSource(homeDir.c_str());
- snapshot.GetDirectory().SetRelativePathTopBinary(homeOutDir.c_str());
cmMakefile mf(cm.GetGlobalGenerator(), snapshot);
auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf);
+ // FIXME: With advanced add_subdirectory usage, these are
+ // not necessarily the same as the generator originally used.
+ // We should pass all these directories through an info file.
+ lgd->SetRelativePathTopSource(homeDir);
+ lgd->SetRelativePathTopBinary(homeOutDir);
+
return cmTransformDepfile(format, *lgd, args[8], args[9]) ? 0 : 2;
}
return 1;
}
}
- CMakeCommandUsage(args[0].c_str());
+ CMakeCommandUsage(args[0]);
return 1;
}
@@ -1601,14 +1611,18 @@ int cmcmd::SymlinkLibrary(std::vector<std::string> const& args)
cmSystemTools::ConvertToUnixSlashes(soName);
cmSystemTools::ConvertToUnixSlashes(name);
if (soName != realName) {
- if (!cmcmd::SymlinkInternal(realName, soName)) {
- cmSystemTools::ReportLastSystemError("cmake_symlink_library");
+ cmsys::Status status = cmcmd::SymlinkInternal(realName, soName);
+ if (!status) {
+ cmSystemTools::Error(
+ cmStrCat("cmake_symlink_library: System Error: ", status.GetString()));
result = 1;
}
}
if (name != soName) {
- if (!cmcmd::SymlinkInternal(soName, name)) {
- cmSystemTools::ReportLastSystemError("cmake_symlink_library");
+ cmsys::Status status = cmcmd::SymlinkInternal(soName, name);
+ if (!status) {
+ cmSystemTools::Error(
+ cmStrCat("cmake_symlink_library: System Error: ", status.GetString()));
result = 1;
}
}
@@ -1621,23 +1635,37 @@ int cmcmd::SymlinkExecutable(std::vector<std::string> const& args)
std::string const& realName = args[2];
std::string const& name = args[3];
if (name != realName) {
- if (!cmcmd::SymlinkInternal(realName, name)) {
- cmSystemTools::ReportLastSystemError("cmake_symlink_executable");
+ cmsys::Status status = cmcmd::SymlinkInternal(realName, name);
+ if (!status) {
+ cmSystemTools::Error(cmStrCat("cmake_symlink_executable: System Error: ",
+ status.GetString()));
result = 1;
}
}
return result;
}
-bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link)
+cmsys::Status cmcmd::SymlinkInternal(std::string const& file,
+ std::string const& link)
{
if (cmSystemTools::FileExists(link) || cmSystemTools::FileIsSymlink(link)) {
cmSystemTools::RemoveFile(link);
}
+ std::string linktext = cmSystemTools::GetFilenameName(file);
#if defined(_WIN32) && !defined(__CYGWIN__)
- return cmSystemTools::CopyFileAlways(file, link);
+ std::string errorMessage;
+ cmsys::Status status =
+ cmSystemTools::CreateSymlink(linktext, link, &errorMessage);
+ // 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);
+ }
+ return status;
#else
- std::string linktext = cmSystemTools::GetFilenameName(file);
return cmSystemTools::CreateSymlink(linktext, link);
#endif
}
@@ -1927,8 +1955,8 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
skipNextArg = false;
continue;
}
- // We use ++ as seperator between the preprocessing step definition and
- // the rc compilation step becase we need to prepend a -- to seperate the
+ // We use ++ as separator between the preprocessing step definition and
+ // the rc compilation step because we need to prepend a -- to separate the
// source file properly from other options when using clang-cl for
// preprocessing.
if (arg == "++") {
diff --git a/Source/cmcmd.h b/Source/cmcmd.h
index a2e0b1ea3..ba78edb00 100644
--- a/Source/cmcmd.h
+++ b/Source/cmcmd.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "cmsys/Status.hxx"
+
#include "cmCryptoHash.h"
class cmConsoleBuf;
@@ -28,8 +30,8 @@ protected:
cmCryptoHash::Algo algo);
static int SymlinkLibrary(std::vector<std::string> const& args);
static int SymlinkExecutable(std::vector<std::string> const& args);
- static bool SymlinkInternal(std::string const& file,
- std::string const& link);
+ static cmsys::Status SymlinkInternal(std::string const& file,
+ std::string const& link);
static int ExecuteEchoColor(std::vector<std::string> const& args);
static int ExecuteLinkScript(std::vector<std::string> const& args);
static int WindowsCEEnvironment(const char* version,
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 3c331d32b..cad27fac4 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -50,13 +50,15 @@ static const char* cmDocumentationOptions[][2] = {
"given number of jobs." },
{ "-Q,--quiet", "Make ctest quiet." },
{ "-O <file>, --output-log <file>", "Output to log file" },
+ { "--output-junit <file>", "Output test results to JUnit XML file." },
{ "-N,--show-only[=format]",
"Disable actual execution of tests. The optional 'format' defines the "
"format of the test information and can be 'human' for the current text "
"format or 'json-v1' for json format. Defaults to 'human'." },
{ "-L <regex>, --label-regex <regex>",
- "Run tests with labels matching "
- "regular expression." },
+ "Run tests with labels matching regular expression. "
+ "With multiple -L, run tests where each "
+ "regular expression matches at least one label." },
{ "-R <regex>, --tests-regex <regex>",
"Run tests matching regular "
"expression." },
@@ -64,8 +66,9 @@ static const char* cmDocumentationOptions[][2] = {
"Exclude tests matching regular "
"expression." },
{ "-LE <regex>, --label-exclude <regex>",
- "Exclude tests with labels "
- "matching regular expression." },
+ "Exclude tests with labels matching regular expression. "
+ "With multiple -LE, exclude tests where each "
+ "regular expression matches at least one label." },
{ "-FA <regex>, --fixture-exclude-any <regex>",
"Do not automatically "
"add any tests for "
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index b0a854292..ef615b3fe 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -98,6 +98,16 @@ foreach(p
endif()
endforeach()
+# Some configure checks depend upon the deployment target. Clear checks when
+# the deployment target changes.
+if (APPLE)
+ if (NOT CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL KWSYS_LAST_OSX_DEPLOYMENT_TARGET)
+ unset(KWSYS_CXX_HAS_UTIMENSAT CACHE)
+ endif ()
+ set(KWSYS_LAST_OSX_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}"
+ CACHE INTERNAL "remember the last deployment target to trigger configure rechecks")
+endif ()
+
#-----------------------------------------------------------------------------
# If a namespace is not specified, use "kwsys" and enable testing.
# This should be the case only when kwsys is not included inside
@@ -142,6 +152,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
set(KWSYS_USE_MD5 1)
set(KWSYS_USE_Process 1)
set(KWSYS_USE_RegularExpression 1)
+ set(KWSYS_USE_Status 1)
set(KWSYS_USE_System 1)
set(KWSYS_USE_SystemTools 1)
set(KWSYS_USE_CommandLineArguments 1)
@@ -157,6 +168,7 @@ if(KWSYS_USE_SystemTools)
set(KWSYS_USE_Directory 1)
set(KWSYS_USE_FStream 1)
set(KWSYS_USE_Encoding 1)
+ set(KWSYS_USE_Status 1)
endif()
if(KWSYS_USE_Glob)
set(KWSYS_USE_Directory 1)
@@ -177,6 +189,7 @@ if(KWSYS_USE_System)
endif()
if(KWSYS_USE_Directory)
set(KWSYS_USE_Encoding 1)
+ set(KWSYS_USE_Status 1)
endif()
if(KWSYS_USE_DynamicLoader)
set(KWSYS_USE_Encoding 1)
@@ -630,7 +643,7 @@ set(KWSYS_HXX_FILES Configure String)
# Add selected C++ classes.
set(cppclasses
Directory DynamicLoader Encoding Glob RegularExpression SystemTools
- CommandLineArguments FStream SystemInformation ConsoleBuf
+ CommandLineArguments FStream SystemInformation ConsoleBuf Status
)
foreach(cpp ${cppclasses})
if(KWSYS_USE_${cpp})
@@ -963,6 +976,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
# C++ tests
set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
testConfigure.cxx
+ testStatus.cxx
testSystemTools.cxx
testCommandLineArguments.cxx
testCommandLineArguments1.cxx
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 0c2190aee..2e8aa83f4 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -94,7 +94,7 @@ void Directory::Clear()
namespace KWSYS_NAMESPACE {
-bool Directory::Load(const std::string& name, std::string* errorMessage)
+Status Directory::Load(std::string const& name, std::string* errorMessage)
{
this->Clear();
intptr_t srchHandle;
@@ -121,7 +121,11 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
delete[] buf;
if (srchHandle == -1) {
- return 0;
+ Status status = Status::POSIX_errno();
+ if (errorMessage) {
+ *errorMessage = status.GetString();
+ }
+ return status;
}
// Loop through names
@@ -129,7 +133,14 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
this->Internal->Files.push_back(Encoding::ToNarrow(data.name));
} while (_wfindnext(srchHandle, &data) != -1);
this->Internal->Path = name;
- return _findclose(srchHandle) != -1;
+ if (_findclose(srchHandle) == -1) {
+ Status status = Status::POSIX_errno();
+ if (errorMessage) {
+ *errorMessage = status.GetString();
+ }
+ return status;
+ }
+ return Status::Success();
}
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
@@ -152,6 +163,20 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
delete[] buf;
if (srchHandle == -1) {
+ if (errorMessage) {
+ if (unsigned int errorId = GetLastError()) {
+ LPSTR message = nullptr;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, nullptr);
+ *errorMessage = std::string(message, size);
+ LocalFree(message);
+ } else {
+ *errorMessage = "Unknown error.";
+ }
+ }
return 0;
}
@@ -192,7 +217,7 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
namespace KWSYS_NAMESPACE {
-bool Directory::Load(const std::string& name, std::string* errorMessage)
+Status Directory::Load(std::string const& name, std::string* errorMessage)
{
this->Clear();
@@ -203,7 +228,7 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
if (errorMessage != nullptr) {
*errorMessage = std::string(strerror(errno));
}
- return false;
+ return Status::POSIX_errno();
}
errno = 0;
@@ -214,12 +239,12 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
if (errorMessage != nullptr) {
*errorMessage = std::string(strerror(errno));
}
- return false;
+ return Status::POSIX_errno();
}
this->Internal->Path = name;
closedir(dir);
- return true;
+ return Status::Success();
}
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in
index 7bc9db024..d50111615 100644
--- a/Source/kwsys/Directory.hxx.in
+++ b/Source/kwsys/Directory.hxx.in
@@ -4,6 +4,7 @@
#define @KWSYS_NAMESPACE@_Directory_hxx
#include <@KWSYS_NAMESPACE@/Configure.h>
+#include <@KWSYS_NAMESPACE@/Status.hxx>
#include <string>
@@ -32,10 +33,9 @@ public:
/**
* Load the specified directory and load the names of the files
- * in that directory. 0 is returned if the directory can not be
- * opened, 1 if it is opened.
+ * in that directory.
*/
- bool Load(const std::string&, std::string* errorMessage = nullptr);
+ Status Load(std::string const&, std::string* errorMessage = nullptr);
/**
* Return the number of files in the current directory.
diff --git a/Source/kwsys/EncodingC.c b/Source/kwsys/EncodingC.c
index e12236afe..13127f1ac 100644
--- a/Source/kwsys/EncodingC.c
+++ b/Source/kwsys/EncodingC.c
@@ -60,7 +60,7 @@ size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* str, size_t n)
char* kwsysEncoding_DupToNarrow(const wchar_t* str)
{
char* ret = NULL;
- size_t length = kwsysEncoding_wcstombs(0, str, 0) + 1;
+ size_t length = kwsysEncoding_wcstombs(NULL, str, 0) + 1;
if (length > 0) {
ret = (char*)malloc(length);
if (ret) {
diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in
index e8474e200..fd3977541 100644
--- a/Source/kwsys/Glob.hxx.in
+++ b/Source/kwsys/Glob.hxx.in
@@ -54,6 +54,9 @@ public:
Glob();
~Glob();
+ Glob(const Glob&) = delete;
+ void operator=(const Glob&) = delete;
+
//! Find all files that match the pattern.
bool FindFiles(const std::string& inexpr, GlobMessages* messages = nullptr);
@@ -124,10 +127,6 @@ protected:
std::vector<std::string> VisitedSymlinks;
bool ListDirs;
bool RecurseListDirs;
-
-private:
- Glob(const Glob&) = delete;
- void operator=(const Glob&) = delete;
};
} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index e1e7721b4..a8a15ddb0 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -122,6 +122,10 @@ static inline void kwsysProcess_usleep(unsigned int msec)
/* The maximum amount to read from a pipe at a time. */
#define KWSYSPE_PIPE_BUFFER_SIZE 1024
+#if defined(__NVCOMPILER)
+# pragma diag_suppress 550 /* variable set but never used (in FD_ZERO) */
+#endif
+
/* Keep track of times using a signed representation. Switch to the
native (possibly unsigned) representation only when calling native
functions. */
@@ -2890,10 +2894,10 @@ static void kwsysProcessesSignalHandler(int signum
/* Re-Install our handler. Repeat call until it is not interrupted. */
{
struct sigaction newSigAction;
- struct sigaction& oldSigAction;
+ struct sigaction* oldSigAction;
memset(&newSigAction, 0, sizeof(struct sigaction));
- newSigChldAction.sa_handler = kwsysProcessesSignalHandler;
- newSigChldAction.sa_flags = SA_NOCLDSTOP;
+ newSigAction.sa_handler = kwsysProcessesSignalHandler;
+ newSigAction.sa_flags = SA_NOCLDSTOP;
sigemptyset(&newSigAction.sa_mask);
switch (signum) {
case SIGCHLD:
@@ -2908,7 +2912,7 @@ static void kwsysProcessesSignalHandler(int signum
oldSigAction = &kwsysProcessesOldSigTermAction;
break;
default:
- return 0;
+ return;
}
while ((sigaction(signum, &newSigAction, oldSigAction) < 0) &&
(errno == EINTR))
diff --git a/Source/kwsys/Status.cxx b/Source/kwsys/Status.cxx
new file mode 100644
index 000000000..503d1e1d5
--- /dev/null
+++ b/Source/kwsys/Status.cxx
@@ -0,0 +1,60 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Status.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+# include "Status.hxx.in"
+#endif
+
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#if defined(_WIN32)
+# include <windows.h>
+#endif
+
+namespace KWSYS_NAMESPACE {
+
+Status Status::POSIX_errno()
+{
+ return Status::POSIX(errno);
+}
+
+#ifdef _WIN32
+Status Status::Windows_GetLastError()
+{
+ return Status::Windows(GetLastError());
+}
+#endif
+
+std::string Status::GetString() const
+{
+ std::string err;
+ switch (this->Kind_) {
+ case Kind::Success:
+ err = "Success";
+ break;
+ case Kind::POSIX:
+ err = strerror(this->POSIX_);
+ break;
+#ifdef _WIN32
+ case Kind::Windows: {
+ LPSTR message = NULL;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, this->Windows_, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, NULL);
+ err = std::string(message, size);
+ LocalFree(message);
+ } break;
+#endif
+ };
+ return err;
+}
+
+} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/Status.hxx.in b/Source/kwsys/Status.hxx.in
new file mode 100644
index 000000000..ed46d5c2b
--- /dev/null
+++ b/Source/kwsys/Status.hxx.in
@@ -0,0 +1,101 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#ifndef @KWSYS_NAMESPACE@_Status_hxx
+#define @KWSYS_NAMESPACE@_Status_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+#include <string>
+
+namespace @KWSYS_NAMESPACE@ {
+
+/** \class Status
+ * \brief OS-specific status of a system operation.
+ */
+class @KWSYS_NAMESPACE@_EXPORT Status
+{
+public:
+ enum class Kind
+ {
+ Success,
+ POSIX,
+#ifdef _WIN32
+ Windows,
+#endif
+ };
+
+ /** Construct with kind "Success". */
+ Status() = default;
+
+ /** Construct with kind "Success". */
+ static Status Success() { return Status(); }
+
+ /** Construct with kind "POSIX" using given errno-style value. */
+ static Status POSIX(int e)
+ {
+ Status s(Kind::POSIX);
+ s.POSIX_ = e;
+ return s;
+ }
+
+ /** Construct with kind "POSIX" using errno. */
+ static Status POSIX_errno();
+
+#ifdef _WIN32
+ /** Construct with kind "Windows" using given GetLastError()-style value. */
+ static Status Windows(unsigned int e)
+ {
+ Status s(Kind::Windows);
+ s.Windows_ = e;
+ return s;
+ }
+
+ /** Construct with kind "Windows" using GetLastError(). */
+ static Status Windows_GetLastError();
+#endif
+
+ /** Return true on "Success", false otherwise. */
+ explicit operator bool() const { return this->Kind_ == Kind::Success; }
+
+ /** Return the kind of status. */
+ Kind GetKind() const { return this->Kind_; }
+
+ /** If the kind is "POSIX", returns the errno-style value.
+ Otherwise, returns 0. */
+ int GetPOSIX() const
+ {
+ return this->Kind_ == Kind::POSIX ? this->POSIX_ : 0;
+ }
+
+#ifdef _WIN32
+ /** If the kind is "Windows", returns the GetLastError()-style value.
+ Otherwise, returns 0. */
+ unsigned int GetWindows() const
+ {
+ return this->Kind_ == Kind::Windows ? this->Windows_ : 0;
+ }
+#endif
+
+ /** Return a human-readable description of the status. */
+ std::string GetString() const;
+
+private:
+ Status(Kind kind)
+ : Kind_(kind)
+ {
+ }
+
+ Kind Kind_ = Kind::Success;
+
+ union
+ {
+ int POSIX_;
+#ifdef _WIN32
+ unsigned int Windows_;
+#endif
+ };
+};
+
+} // namespace @KWSYS_NAMESPACE@
+
+#endif
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 7743eabe9..12f9139cc 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1383,7 +1383,7 @@ void SymbolProperties::Initialize(void* address)
}
# else
// second fallback use builtin backtrace_symbols
-// to decode the bactrace.
+// to decode the backtrace.
# endif
}
#endif // don't define this class if we're not using it
@@ -3472,6 +3472,10 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
// We want to record the total number of cores in this->NumberOfPhysicalCPU
// (checking only the first proc)
std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores");
+ if (Cores.empty()) {
+ // Linux Sparc is different
+ Cores = this->ExtractValueFromCpuInfoFile(buffer, "ncpus probed");
+ }
auto NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str());
NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u);
this->NumberOfPhysicalCPU =
@@ -3490,6 +3494,9 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
if (this->NumberOfPhysicalCPU <= 0) {
this->NumberOfPhysicalCPU = 1;
}
+ if (this->NumberOfLogicalCPU == 0) {
+ this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
+ }
// LogicalProcessorsPerPhysical>1 => SMT.
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU;
@@ -3503,8 +3510,18 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
else {
// Linux Sparc: CPU speed is in Hz and encoded in hexadecimal
CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "Cpu0ClkTck");
- this->CPUSpeedInMHz =
- static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 16)) / 1000000.0f;
+ if (!CPUSpeed.empty()) {
+ this->CPUSpeedInMHz =
+ static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 16)) /
+ 1000000.0f;
+ } else {
+ // if the kernel is build as Sparc32 it's in decimal, note the different
+ // case
+ CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "CPU0ClkTck");
+ this->CPUSpeedInMHz =
+ static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 10)) /
+ 1000000.0f;
+ }
}
#endif
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 6144d9c04..006495d3c 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -93,9 +93,43 @@
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
# endif
+# ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
+# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2)
+# endif
# if defined(_MSC_VER) && _MSC_VER >= 1800
# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# endif
+// from ntifs.h, which can only be used by drivers
+typedef struct _REPARSE_DATA_BUFFER
+{
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union
+ {
+ struct
+ {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct
+ {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct
+ {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ } DUMMYUNIONNAME;
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#endif
#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
@@ -244,7 +278,7 @@ inline int Chdir(const std::string& dir)
return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
}
inline void Realpath(const std::string& path, std::string& resolved_path,
- std::string* errorMessage = 0)
+ std::string* errorMessage = nullptr)
{
std::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path);
wchar_t* ptemp;
@@ -882,21 +916,24 @@ FILE* SystemTools::Fopen(const std::string& file, const char* mode)
#endif
}
-bool SystemTools::MakeDirectory(const char* path, const mode_t* mode)
+Status SystemTools::MakeDirectory(const char* path, const mode_t* mode)
{
if (!path) {
- return false;
+ return Status::POSIX(EINVAL);
}
return SystemTools::MakeDirectory(std::string(path), mode);
}
-bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode)
+Status SystemTools::MakeDirectory(std::string const& path, const mode_t* mode)
{
- if (SystemTools::PathExists(path)) {
- return SystemTools::FileIsDirectory(path);
- }
if (path.empty()) {
- return false;
+ return Status::POSIX(EINVAL);
+ }
+ if (SystemTools::PathExists(path)) {
+ if (SystemTools::FileIsDirectory(path)) {
+ return Status::Success();
+ }
+ return Status::POSIX(EEXIST);
}
std::string dir = path;
SystemTools::ConvertToUnixSlashes(dir);
@@ -914,15 +951,11 @@ bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode)
++pos;
}
topdir = dir;
- if (Mkdir(topdir, mode) != 0) {
- // if it is some other error besides directory exists
- // then return false
- if (errno != EEXIST) {
- return false;
- }
+ if (Mkdir(topdir, mode) != 0 && errno != EEXIST) {
+ return Status::POSIX_errno();
}
- return true;
+ return Status::Success();
}
// replace replace with with as many times as it shows up in source.
@@ -1411,18 +1444,18 @@ int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf)
#endif
}
-bool SystemTools::Touch(const std::string& filename, bool create)
+Status SystemTools::Touch(std::string const& filename, bool create)
{
if (!SystemTools::FileExists(filename)) {
if (create) {
FILE* file = Fopen(filename, "a+b");
if (file) {
fclose(file);
- return true;
+ return Status::Success();
}
- return false;
+ return Status::POSIX_errno();
} else {
- return true;
+ return Status::Success();
}
}
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -1430,31 +1463,32 @@ bool SystemTools::Touch(const std::string& filename, bool create)
FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if (!h) {
- return false;
+ return Status::Windows_GetLastError();
}
FILETIME mtime;
GetSystemTimeAsFileTime(&mtime);
if (!SetFileTime(h, 0, 0, &mtime)) {
+ Status status = Status::Windows_GetLastError();
CloseHandle(h);
- return false;
+ return status;
}
CloseHandle(h);
#elif KWSYS_CXX_HAS_UTIMENSAT
// utimensat is only available on newer Unixes and macOS 10.13+
if (utimensat(AT_FDCWD, filename.c_str(), nullptr, 0) < 0) {
- return false;
+ return Status::POSIX_errno();
}
#else
// fall back to utimes
if (utimes(filename.c_str(), nullptr) < 0) {
- return false;
+ return Status::POSIX_errno();
}
#endif
- return true;
+ return Status::Success();
}
-bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
- int* result)
+Status SystemTools::FileTimeCompare(std::string const& f1,
+ std::string const& f2, int* result)
{
// Default to same time.
*result = 0;
@@ -1462,11 +1496,11 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
// POSIX version. Use stat function to get file modification time.
struct stat s1;
if (stat(f1.c_str(), &s1) != 0) {
- return false;
+ return Status::POSIX_errno();
}
struct stat s2;
if (stat(f2.c_str(), &s2) != 0) {
- return false;
+ return Status::POSIX_errno();
}
# if KWSYS_CXX_STAT_HAS_ST_MTIM
// Compare using nanosecond resolution.
@@ -1504,17 +1538,17 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
WIN32_FILE_ATTRIBUTE_DATA f2d;
if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f1).c_str(),
GetFileExInfoStandard, &f1d)) {
- return false;
+ return Status::Windows_GetLastError();
}
if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f2).c_str(),
GetFileExInfoStandard, &f2d)) {
- return false;
+ return Status::Windows_GetLastError();
}
// Compare the file times using resolution provided by system call.
*result = (int)CompareFileTime(&f1d.ftLastWriteTime, &f2d.ftLastWriteTime);
#endif
- return true;
+ return Status::Success();
}
// Return a capitalized string (i.e the first letter is uppercased, all other
@@ -2129,8 +2163,8 @@ static std::string FileInDir(const std::string& source, const std::string& dir)
return new_destination + '/' + SystemTools::GetFilenameName(source);
}
-bool SystemTools::CopyFileIfDifferent(const std::string& source,
- const std::string& destination)
+Status SystemTools::CopyFileIfDifferent(std::string const& source,
+ std::string const& destination)
{
// special check for a destination that is a directory
// FilesDiffer does not handle file to directory compare
@@ -2147,7 +2181,7 @@ bool SystemTools::CopyFileIfDifferent(const std::string& source,
}
}
// at this point the files must be the same so return true
- return true;
+ return Status::Success();
}
#define KWSYS_ST_BUFFER 4096
@@ -2273,16 +2307,13 @@ bool SystemTools::TextFilesDiffer(const std::string& path1,
return false;
}
-/**
- * Blockwise copy source to destination file
- */
-static bool CopyFileContentBlockwise(const std::string& source,
- const std::string& destination)
+Status SystemTools::CopyFileContentBlockwise(std::string const& source,
+ std::string const& destination)
{
// Open files
kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
if (!fin) {
- return false;
+ return Status::POSIX_errno();
}
// try and remove the destination file so that read only destination files
@@ -2294,7 +2325,7 @@ static bool CopyFileContentBlockwise(const std::string& source,
kwsys::ofstream fout(destination.c_str(),
std::ios::out | std::ios::trunc | std::ios::binary);
if (!fout) {
- return false;
+ return Status::POSIX_errno();
}
// This copy loop is very sensitive on certain platforms with
@@ -2323,10 +2354,10 @@ static bool CopyFileContentBlockwise(const std::string& source,
fout.close();
if (!fout) {
- return false;
+ return Status::POSIX_errno();
}
- return true;
+ return Status::Success();
}
/**
@@ -2341,13 +2372,13 @@ static bool CopyFileContentBlockwise(const std::string& source,
* - The underlying filesystem does not support file cloning
* - An unspecified error occurred
*/
-static bool CloneFileContent(const std::string& source,
- const std::string& destination)
+Status SystemTools::CloneFileContent(std::string const& source,
+ std::string const& destination)
{
#if defined(__linux) && defined(FICLONE)
int in = open(source.c_str(), O_RDONLY);
if (in < 0) {
- return false;
+ return Status::POSIX_errno();
}
SystemTools::RemoveFile(destination);
@@ -2355,38 +2386,42 @@ static bool CloneFileContent(const std::string& source,
int out =
open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (out < 0) {
+ Status status = Status::POSIX_errno();
close(in);
- return false;
+ return status;
}
- int result = ioctl(out, FICLONE, in);
+ Status status = Status::Success();
+ if (ioctl(out, FICLONE, in) < 0) {
+ status = Status::POSIX_errno();
+ }
close(in);
close(out);
- if (result < 0) {
- return false;
- }
-
- return true;
+ return status;
#else
(void)source;
(void)destination;
- return false;
+ return Status::POSIX(ENOSYS);
#endif
}
/**
* Copy a file named by "source" to the file named by "destination".
*/
-bool SystemTools::CopyFileAlways(const std::string& source,
- const std::string& destination)
+Status SystemTools::CopyFileAlways(std::string const& source,
+ std::string const& destination)
{
+ Status status;
mode_t perm = 0;
- bool perms = SystemTools::GetPermissions(source, perm);
+ Status perms = SystemTools::GetPermissions(source, perm);
std::string real_destination = destination;
if (SystemTools::FileIsDirectory(source)) {
- SystemTools::MakeDirectory(destination);
+ status = SystemTools::MakeDirectory(destination);
+ if (!status) {
+ return status;
+ }
} else {
// If destination is a directory, try to create a file with the same
// name as the source in that directory.
@@ -2403,30 +2438,34 @@ bool SystemTools::CopyFileAlways(const std::string& source,
}
// If files are the same do not copy
if (SystemTools::SameFile(source, real_destination)) {
- return true;
+ return status;
}
// Create destination directory
-
- SystemTools::MakeDirectory(destination_dir);
-
- if (!CloneFileContent(source, real_destination)) {
- // if cloning did not succeed, fall back to blockwise copy
- if (!CopyFileContentBlockwise(source, real_destination)) {
- return false;
+ if (!destination_dir.empty()) {
+ status = SystemTools::MakeDirectory(destination_dir);
+ if (!status) {
+ return status;
}
}
+
+ status = SystemTools::CloneFileContent(source, real_destination);
+ // if cloning did not succeed, fall back to blockwise copy
+ if (!status) {
+ status = SystemTools::CopyFileContentBlockwise(source, real_destination);
+ }
+ if (!status) {
+ return status;
+ }
}
if (perms) {
- if (!SystemTools::SetPermissions(real_destination, perm)) {
- return false;
- }
+ status = SystemTools::SetPermissions(real_destination, perm);
}
- return true;
+ return status;
}
-bool SystemTools::CopyAFile(const std::string& source,
- const std::string& destination, bool always)
+Status SystemTools::CopyAFile(std::string const& source,
+ std::string const& destination, bool always)
{
if (always) {
return SystemTools::CopyFileAlways(source, destination);
@@ -2439,18 +2478,21 @@ bool SystemTools::CopyAFile(const std::string& source,
* Copy a directory content from "source" directory to the directory named by
* "destination".
*/
-bool SystemTools::CopyADirectory(const std::string& source,
- const std::string& destination, bool always)
+Status SystemTools::CopyADirectory(std::string const& source,
+ std::string const& destination, bool always)
{
+ Status status;
Directory dir;
- if (dir.Load(source) == 0) {
- return false;
+ status = dir.Load(source);
+ if (!status) {
+ return status;
}
- size_t fileNum;
- if (!SystemTools::MakeDirectory(destination)) {
- return false;
+ status = SystemTools::MakeDirectory(destination);
+ if (!status) {
+ return status;
}
- for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
+
+ for (size_t fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 &&
strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..") != 0) {
std::string fullPath = source;
@@ -2460,18 +2502,20 @@ bool SystemTools::CopyADirectory(const std::string& source,
std::string fullDestPath = destination;
fullDestPath += "/";
fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
- if (!SystemTools::CopyADirectory(fullPath, fullDestPath, always)) {
- return false;
+ status = SystemTools::CopyADirectory(fullPath, fullDestPath, always);
+ if (!status) {
+ return status;
}
} else {
- if (!SystemTools::CopyAFile(fullPath, destination, always)) {
- return false;
+ status = SystemTools::CopyAFile(fullPath, destination, always);
+ if (!status) {
+ return status;
}
}
}
}
- return true;
+ return status;
}
// return size of file; also returns zero if no file exists
@@ -2553,26 +2597,26 @@ std::string SystemTools::GetLastSystemError()
return strerror(e);
}
-bool SystemTools::RemoveFile(const std::string& source)
+Status SystemTools::RemoveFile(std::string const& source)
{
#ifdef _WIN32
std::wstring const& ws = Encoding::ToWindowsExtendedPath(source);
if (DeleteFileW(ws.c_str())) {
- return true;
+ return Status::Success();
}
DWORD err = GetLastError();
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
- return true;
+ return Status::Success();
}
if (err != ERROR_ACCESS_DENIED) {
- return false;
+ return Status::Windows(err);
}
/* The file may be read-only. Try adding write permission. */
mode_t mode;
if (!SystemTools::GetPermissions(source, mode) ||
!SystemTools::SetPermissions(source, S_IWRITE)) {
SetLastError(err);
- return false;
+ return Status::Windows(err);
}
const DWORD DIRECTORY_SOFT_LINK_ATTRS =
@@ -2581,26 +2625,29 @@ bool SystemTools::RemoveFile(const std::string& source)
if (attrs != INVALID_FILE_ATTRIBUTES &&
(attrs & DIRECTORY_SOFT_LINK_ATTRS) == DIRECTORY_SOFT_LINK_ATTRS &&
RemoveDirectoryW(ws.c_str())) {
- return true;
+ return Status::Success();
}
if (DeleteFileW(ws.c_str()) || GetLastError() == ERROR_FILE_NOT_FOUND ||
GetLastError() == ERROR_PATH_NOT_FOUND) {
- return true;
+ return Status::Success();
}
/* Try to restore the original permissions. */
SystemTools::SetPermissions(source, mode);
SetLastError(err);
- return false;
+ return Status::Windows(err);
#else
- return unlink(source.c_str()) == 0 || errno == ENOENT;
+ if (unlink(source.c_str()) != 0 && errno != ENOENT) {
+ return Status::POSIX_errno();
+ }
+ return Status::Success();
#endif
}
-bool SystemTools::RemoveADirectory(const std::string& source)
+Status SystemTools::RemoveADirectory(std::string const& source)
{
// Add write permission to the directory so we can modify its
// content to remove files and directories from it.
- mode_t mode;
+ mode_t mode = 0;
if (SystemTools::GetPermissions(source, mode)) {
#if defined(_WIN32) && !defined(__CYGWIN__)
mode |= S_IWRITE;
@@ -2610,8 +2657,13 @@ bool SystemTools::RemoveADirectory(const std::string& source)
SystemTools::SetPermissions(source, mode);
}
+ Status status;
Directory dir;
- dir.Load(source);
+ status = dir.Load(source);
+ if (!status) {
+ return status;
+ }
+
size_t fileNum;
for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 &&
@@ -2621,18 +2673,23 @@ bool SystemTools::RemoveADirectory(const std::string& source)
fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
if (SystemTools::FileIsDirectory(fullPath) &&
!SystemTools::FileIsSymlink(fullPath)) {
- if (!SystemTools::RemoveADirectory(fullPath)) {
- return false;
+ status = SystemTools::RemoveADirectory(fullPath);
+ if (!status) {
+ return status;
}
} else {
- if (!SystemTools::RemoveFile(fullPath)) {
- return false;
+ status = SystemTools::RemoveFile(fullPath);
+ if (!status) {
+ return status;
}
}
}
}
- return (Rmdir(source) == 0);
+ if (Rmdir(source) != 0) {
+ status = Status::POSIX_errno();
+ }
+ return status;
}
/**
@@ -2985,7 +3042,7 @@ bool SystemTools::FileIsSymlink(const std::string& name)
}
CloseHandle(hFile);
ULONG reparseTag =
- reinterpret_cast<PREPARSE_GUID_DATA_BUFFER>(&buffer[0])->ReparseTag;
+ reinterpret_cast<PREPARSE_DATA_BUFFER>(&buffer[0])->ReparseTag;
return (reparseTag == IO_REPARSE_TAG_SYMLINK) ||
(reparseTag == IO_REPARSE_TAG_MOUNT_POINT);
}
@@ -3025,45 +3082,109 @@ bool SystemTools::FileIsFIFO(const std::string& name)
#endif
}
-#if defined(_WIN32) && !defined(__CYGWIN__)
-bool SystemTools::CreateSymlink(const std::string&, const std::string&)
+Status SystemTools::CreateSymlink(std::string const& origName,
+ std::string const& newName)
{
- return false;
-}
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ DWORD flags;
+ if (FileIsDirectory(origName)) {
+ flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
+ } else {
+ flags = 0;
+ }
+
+ std::wstring origPath = Encoding::ToWindowsExtendedPath(origName);
+ std::wstring newPath = Encoding::ToWindowsExtendedPath(newName);
+
+ Status status;
+ if (!CreateSymbolicLinkW(newPath.c_str(), origPath.c_str(),
+ flags |
+ SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) {
+ status = Status::Windows_GetLastError();
+ }
+ // Older Windows versions do not understand
+ // SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
+ if (status.GetWindows() == ERROR_INVALID_PARAMETER) {
+ status = Status::Success();
+ if (!CreateSymbolicLinkW(newPath.c_str(), origPath.c_str(), flags)) {
+ status = Status::Windows_GetLastError();
+ }
+ }
+
+ return status;
#else
-bool SystemTools::CreateSymlink(const std::string& origName,
- const std::string& newName)
-{
- return symlink(origName.c_str(), newName.c_str()) >= 0;
-}
+ if (symlink(origName.c_str(), newName.c_str()) < 0) {
+ return Status::POSIX_errno();
+ }
+ return Status::Success();
#endif
+}
-#if defined(_WIN32) && !defined(__CYGWIN__)
-bool SystemTools::ReadSymlink(const std::string&, std::string&)
+Status SystemTools::ReadSymlink(std::string const& newName,
+ std::string& origName)
{
- return false;
-}
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ std::wstring newPath = Encoding::ToWindowsExtendedPath(newName);
+ // FILE_ATTRIBUTE_REPARSE_POINT means:
+ // * a file or directory that has an associated reparse point, or
+ // * a file that is a symbolic link.
+ HANDLE hFile = CreateFileW(
+ newPath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return Status::Windows_GetLastError();
+ }
+ byte buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ DWORD bytesReturned = 0;
+ Status status;
+ if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, nullptr, 0, buffer,
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned,
+ nullptr)) {
+ status = Status::Windows_GetLastError();
+ }
+ CloseHandle(hFile);
+ if (!status) {
+ return status;
+ }
+ PREPARSE_DATA_BUFFER data =
+ reinterpret_cast<PREPARSE_DATA_BUFFER>(&buffer[0]);
+ USHORT substituteNameLength;
+ PCWSTR substituteNameData;
+ if (data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
+ substituteNameLength =
+ data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
+ substituteNameData = data->SymbolicLinkReparseBuffer.PathBuffer +
+ data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
+ } else if (data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
+ substituteNameLength =
+ data->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
+ substituteNameData = data->MountPointReparseBuffer.PathBuffer +
+ data->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
+ } else {
+ return Status::Windows(ERROR_REPARSE_TAG_MISMATCH);
+ }
+ std::wstring substituteName(substituteNameData, substituteNameLength);
+ origName = Encoding::ToNarrow(substituteName);
#else
-bool SystemTools::ReadSymlink(const std::string& newName,
- std::string& origName)
-{
char buf[KWSYS_SYSTEMTOOLS_MAXPATH + 1];
int count = static_cast<int>(
readlink(newName.c_str(), buf, KWSYS_SYSTEMTOOLS_MAXPATH));
- if (count >= 0) {
- // Add null-terminator.
- buf[count] = 0;
- origName = buf;
- return true;
- } else {
- return false;
+ if (count < 0) {
+ return Status::POSIX_errno();
}
-}
+ // Add null-terminator.
+ buf[count] = 0;
+ origName = buf;
#endif
+ return Status::Success();
+}
-int SystemTools::ChangeDirectory(const std::string& dir)
+Status SystemTools::ChangeDirectory(std::string const& dir)
{
- return Chdir(dir);
+ if (Chdir(dir) < 0) {
+ return Status::POSIX_errno();
+ }
+ return Status::Success();
}
std::string SystemTools::GetCurrentWorkingDirectory()
@@ -3929,7 +4050,7 @@ bool SystemTools::FileIsFullPath(const char* in_name)
bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len)
{
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
// On Windows, the name must be at least two characters long.
if (len < 2) {
return false;
@@ -3960,7 +4081,8 @@ bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len)
return false;
}
-bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath)
+Status SystemTools::GetShortPath(std::string const& path,
+ std::string& shortPath)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
std::string tempPath = path; // create a buffer
@@ -3980,14 +4102,14 @@ bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath)
}
if (ret == 0) {
- return false;
+ return Status::Windows_GetLastError();
} else {
shortPath = Encoding::ToNarrow(&buffer[0]);
- return true;
+ return Status::Success();
}
#else
shortPath = path;
- return true;
+ return Status::Success();
#endif
}
@@ -4088,21 +4210,21 @@ int SystemTools::GetTerminalWidth()
return width;
}
-bool SystemTools::GetPermissions(const char* file, mode_t& mode)
+Status SystemTools::GetPermissions(const char* file, mode_t& mode)
{
if (!file) {
- return false;
+ return Status::POSIX(EINVAL);
}
return SystemTools::GetPermissions(std::string(file), mode);
}
-bool SystemTools::GetPermissions(const std::string& file, mode_t& mode)
+Status SystemTools::GetPermissions(std::string const& file, mode_t& mode)
{
#if defined(_WIN32)
DWORD attr =
GetFileAttributesW(Encoding::ToWindowsExtendedPath(file).c_str());
if (attr == INVALID_FILE_ATTRIBUTES) {
- return false;
+ return Status::Windows_GetLastError();
}
if ((attr & FILE_ATTRIBUTE_READONLY) != 0) {
mode = (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6));
@@ -4125,27 +4247,27 @@ bool SystemTools::GetPermissions(const std::string& file, mode_t& mode)
#else
struct stat st;
if (stat(file.c_str(), &st) < 0) {
- return false;
+ return Status::POSIX_errno();
}
mode = st.st_mode;
#endif
- return true;
+ return Status::Success();
}
-bool SystemTools::SetPermissions(const char* file, mode_t mode,
- bool honor_umask)
+Status SystemTools::SetPermissions(const char* file, mode_t mode,
+ bool honor_umask)
{
if (!file) {
- return false;
+ return Status::POSIX(EINVAL);
}
return SystemTools::SetPermissions(std::string(file), mode, honor_umask);
}
-bool SystemTools::SetPermissions(const std::string& file, mode_t mode,
- bool honor_umask)
+Status SystemTools::SetPermissions(std::string const& file, mode_t mode,
+ bool honor_umask)
{
if (!SystemTools::PathExists(file)) {
- return false;
+ return Status::POSIX(ENOENT);
}
if (honor_umask) {
mode_t currentMask = umask(0);
@@ -4158,10 +4280,10 @@ bool SystemTools::SetPermissions(const std::string& file, mode_t mode,
if (chmod(file.c_str(), mode) < 0)
#endif
{
- return false;
+ return Status::POSIX_errno();
}
- return true;
+ return Status::Success();
}
std::string SystemTools::GetParentDirectory(const std::string& fileOrDir)
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 74dc17651..e5d115e08 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -4,6 +4,7 @@
#define @KWSYS_NAMESPACE@_SystemTools_hxx
#include <@KWSYS_NAMESPACE@/Configure.hxx>
+#include <@KWSYS_NAMESPACE@/Status.hxx>
#include <iosfwd>
#include <map>
@@ -339,7 +340,7 @@ public:
/**
Change the modification time or create a file
*/
- static bool Touch(const std::string& filename, bool create);
+ static Status Touch(std::string const& filename, bool create);
/**
* Compare file modification times.
@@ -347,8 +348,8 @@ public:
* When true is returned, result has -1, 0, +1 for
* f1 older, same, or newer than f2.
*/
- static bool FileTimeCompare(const std::string& f1, const std::string& f2,
- int* result);
+ static Status FileTimeCompare(std::string const& f1, std::string const& f2,
+ int* result);
/**
* Get the file extension (including ".") needed for an executable
@@ -507,7 +508,7 @@ public:
* For windows return the short path for the given path,
* Unix just a pass through
*/
- static bool GetShortPath(const std::string& path, std::string& result);
+ static Status GetShortPath(std::string const& path, std::string& result);
/**
* Read line from file. Make sure to read a full line and truncates it if
@@ -553,16 +554,16 @@ public:
* can make a full path even if none of the directories existed
* prior to calling this function.
*/
- static bool MakeDirectory(const char* path, const mode_t* mode = nullptr);
- static bool MakeDirectory(const std::string& path,
- const mode_t* mode = nullptr);
+ static Status MakeDirectory(const char* path, const mode_t* mode = nullptr);
+ static Status MakeDirectory(std::string const& path,
+ const mode_t* mode = nullptr);
/**
* Copy the source file to the destination file only
* if the two files differ.
*/
- static bool CopyFileIfDifferent(const std::string& source,
- const std::string& destination);
+ static Status CopyFileIfDifferent(std::string const& source,
+ std::string const& destination);
/**
* Compare the contents of two files. Return true if different
@@ -578,6 +579,17 @@ public:
const std::string& path2);
/**
+ * Blockwise copy source to destination file
+ */
+ static Status CopyFileContentBlockwise(std::string const& source,
+ std::string const& destination);
+ /**
+ * Clone the source file to the destination file
+ */
+ static Status CloneFileContent(std::string const& source,
+ std::string const& destination);
+
+ /**
* Return true if the two files are the same file
*/
static bool SameFile(const std::string& file1, const std::string& file2);
@@ -585,16 +597,16 @@ public:
/**
* Copy a file.
*/
- static bool CopyFileAlways(const std::string& source,
- const std::string& destination);
+ static Status CopyFileAlways(std::string const& source,
+ std::string const& destination);
/**
* Copy a file. If the "always" argument is true the file is always
* copied. If it is false, the file is copied only if it is new or
* has changed.
*/
- static bool CopyAFile(const std::string& source,
- const std::string& destination, bool always = true);
+ static Status CopyAFile(std::string const& source,
+ std::string const& destination, bool always = true);
/**
* Copy content directory to another directory with all files and
@@ -602,19 +614,19 @@ public:
* always copied. If it is false, only files that have changed or
* are new are copied.
*/
- static bool CopyADirectory(const std::string& source,
- const std::string& destination,
- bool always = true);
+ static Status CopyADirectory(std::string const& source,
+ std::string const& destination,
+ bool always = true);
/**
* Remove a file
*/
- static bool RemoveFile(const std::string& source);
+ static Status RemoveFile(std::string const& source);
/**
* Remove a directory
*/
- static bool RemoveADirectory(const std::string& source);
+ static Status RemoveADirectory(std::string const& source);
/**
* Get the maximum full file path length
@@ -708,14 +720,14 @@ public:
* Create a symbolic link if the platform supports it. Returns whether
* creation succeeded.
*/
- static bool CreateSymlink(const std::string& origName,
- const std::string& newName);
+ static Status CreateSymlink(std::string const& origName,
+ std::string const& newName);
/**
* Read the contents of a symbolic link. Returns whether reading
* succeeded.
*/
- static bool ReadSymlink(const std::string& newName, std::string& origName);
+ static Status ReadSymlink(std::string const& newName, std::string& origName);
/**
* Try to locate the file 'filename' in the directory 'dir'.
@@ -765,12 +777,12 @@ public:
* WARNING: A non-thread-safe method is currently used to get the umask
* if a honor_umask parameter is set to true.
*/
- static bool GetPermissions(const char* file, mode_t& mode);
- static bool GetPermissions(const std::string& file, mode_t& mode);
- static bool SetPermissions(const char* file, mode_t mode,
- bool honor_umask = false);
- static bool SetPermissions(const std::string& file, mode_t mode,
- bool honor_umask = false);
+ static Status GetPermissions(const char* file, mode_t& mode);
+ static Status GetPermissions(std::string const& file, mode_t& mode);
+ static Status SetPermissions(const char* file, mode_t mode,
+ bool honor_umask = false);
+ static Status SetPermissions(std::string const& file, mode_t mode,
+ bool honor_umask = false);
/** -----------------------------------------------------------------
* Time Manipulation Routines
@@ -867,7 +879,7 @@ public:
/**
* Change directory to the directory specified
*/
- static int ChangeDirectory(const std::string& dir);
+ static Status ChangeDirectory(std::string const& dir);
/**
* Get the result of strerror(errno)
diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c
index 4d1b46c87..20bb5fe6d 100644
--- a/Source/kwsys/Terminal.c
+++ b/Source/kwsys/Terminal.c
@@ -10,7 +10,7 @@
#endif
/* Configure support for this platform. */
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32)
# define KWSYS_TERMINAL_SUPPORT_CONSOLE
#endif
#if !defined(_WIN32)
@@ -173,6 +173,14 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
}
}
+ /* Disable color according to http://bixense.com/clicolors/ convention. */
+ {
+ const char* clicolor = getenv("CLICOLOR");
+ if (clicolor && strcmp(clicolor, "0") == 0) {
+ return 0;
+ }
+ }
+
/* GNU make 4.1+ may tell us that its output is destined for a TTY. */
{
const char* termout = getenv("MAKE_TERMOUT");
diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx
index eb3ca3254..06a22dc47 100644
--- a/Source/kwsys/testDirectory.cxx
+++ b/Source/kwsys/testDirectory.cxx
@@ -88,7 +88,7 @@ int _nonExistentDirectoryTest()
errorMessage = "foo";
// Increment res failure if directory lists
- res += testdir.Load(testdirpath, &errorMessage);
+ res += testdir.Load(testdirpath, &errorMessage) ? 1 : 0;
#if !defined(_WIN32) || defined(__CYGWIN__)
// Increment res failure if errorMessage is unmodified
res += (errorMessage == "foo");
@@ -120,7 +120,7 @@ int _copyDirectoryTest()
std::cerr << destination << " shouldn't exist before test" << std::endl;
return 2;
}
- const bool copysuccess = SystemTools::CopyADirectory(source, destination);
+ const Status copysuccess = SystemTools::CopyADirectory(source, destination);
const bool destinationexists = SystemTools::PathExists(destination);
if (copysuccess) {
std::cerr << "CopyADirectory should have returned false" << std::endl;
diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx
index 703ad4dcd..9ba204e78 100644
--- a/Source/kwsys/testDynamicLoader.cxx
+++ b/Source/kwsys/testDynamicLoader.cxx
@@ -8,6 +8,25 @@
# include <be/kernel/OS.h> /* disable_debugger() API. */
#endif
+// Needed for __GLIBC__ test macro.
+#ifdef __linux__
+# include <features.h>
+#endif
+
+// Will define LIBDL_SO macro on systems with glibc.
+#ifdef __GLIBC__
+# include <gnu/lib-names.h>
+// Define to LIBC_SO, if not defined by above header.
+# ifndef LIBDL_SO
+# define LIBDL_SO LIBC_SO
+# endif
+#endif
+
+// Define the LIBDL_SO macro, if not defined above.
+#ifndef LIBDL_SO
+# define LIBDL_SO "libdl.so"
+#endif
+
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
@@ -107,8 +126,8 @@ int testDynamicLoader(int argc, char* argv[])
// This one is actually fun to test, since dlopen is by default
// loaded...wonder why :)
res += TestDynamicLoader("foobar.lib", "dlopen", 0, 1, 0);
- res += TestDynamicLoader("libdl.so", "dlopen", 1, 1, 1);
- res += TestDynamicLoader("libdl.so", "TestDynamicLoader", 1, 0, 1);
+ res += TestDynamicLoader(LIBDL_SO, "dlopen", 1, 1, 1);
+ res += TestDynamicLoader(LIBDL_SO, "TestDynamicLoader", 1, 0, 1);
#endif
// Now try on the generated library
std::string libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynload");
diff --git a/Source/kwsys/testStatus.cxx b/Source/kwsys/testStatus.cxx
new file mode 100644
index 000000000..f85ef422d
--- /dev/null
+++ b/Source/kwsys/testStatus.cxx
@@ -0,0 +1,117 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Status.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+# include "Status.hxx.in"
+#endif
+
+#include <cerrno>
+#include <iostream>
+
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+int testStatus(int, char* [])
+{
+ bool res = true;
+ {
+ kwsys::Status status;
+ if (status.GetKind() != kwsys::Status::Kind::Success) {
+ std::cerr << "Status default constructor does not produce Success\n";
+ res = false;
+ }
+
+ status = kwsys::Status::Success();
+ if (status.GetKind() != kwsys::Status::Kind::Success) {
+ std::cerr << "Status Success constructor does not produce Success\n";
+ res = false;
+ }
+ if (!status) {
+ std::cerr << "Status Success kind is not true\n";
+ res = false;
+ }
+ if (status.GetPOSIX() != 0) {
+ std::cerr << "Status Success kind does not return POSIX 0\n";
+ res = false;
+ }
+#ifdef _WIN32
+ if (status.GetWindows() != 0) {
+ std::cerr << "Status Success kind does not return Windows 0\n";
+ res = false;
+ }
+#endif
+ if (status.GetString() != "Success") {
+ std::cerr << "Status Success kind does not return \"Success\" string\n";
+ res = false;
+ }
+
+ status = kwsys::Status::POSIX(EINVAL);
+ if (status.GetKind() != kwsys::Status::Kind::POSIX) {
+ std::cerr << "Status POSIX constructor does not produce POSIX\n";
+ res = false;
+ }
+ if (status) {
+ std::cerr << "Status POSIX kind is not false\n";
+ res = false;
+ }
+ if (status.GetPOSIX() != EINVAL) {
+ std::cerr << "Status POSIX kind does not preserve POSIX value\n";
+ res = false;
+ }
+#ifdef _WIN32
+ if (status.GetWindows() != 0) {
+ std::cerr << "Status POSIX kind does not return Windows 0\n";
+ res = false;
+ }
+#endif
+ if (status.GetString().empty()) {
+ std::cerr << "Status POSIX kind returns empty string\n";
+ res = false;
+ }
+ errno = ENOENT;
+ status = kwsys::Status::POSIX_errno();
+ if (status.GetPOSIX() != ENOENT) {
+ std::cerr << "Status POSIX_errno did not use errno\n";
+ res = false;
+ }
+ errno = 0;
+
+#ifdef _WIN32
+ status = kwsys::Status::Windows(ERROR_INVALID_PARAMETER);
+ if (status.GetKind() != kwsys::Status::Kind::Windows) {
+ std::cerr << "Status Windows constructor does not produce Windows\n";
+ res = false;
+ }
+ if (status) {
+ std::cerr << "Status Windows kind is not false\n";
+ res = false;
+ }
+ if (status.GetWindows() != ERROR_INVALID_PARAMETER) {
+ std::cerr << "Status Windows kind does not preserve Windows value\n";
+ res = false;
+ }
+ if (status.GetPOSIX() != 0) {
+ std::cerr << "Status Windows kind does not return POSIX 0\n";
+ res = false;
+ }
+ if (status.GetString().empty()) {
+ std::cerr << "Status Windows kind returns empty string\n";
+ res = false;
+ }
+
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ status = kwsys::Status::Windows_GetLastError();
+ if (status.GetWindows() != ERROR_FILE_NOT_FOUND) {
+ std::cerr << "Status Windows_GetLastError did not use GetLastError()\n";
+ res = false;
+ }
+ SetLastError(ERROR_SUCCESS);
+#endif
+ }
+ return res ? 0 : 1;
+}
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index cfa420df4..39a19cbf2 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -29,6 +29,7 @@
# ifdef _MSC_VER
# define umask _umask
# endif
+# include <windows.h>
#endif
#include <sys/stat.h> /* umask (POSIX), _S_I* constants (Windows) */
// Visual C++ does not define mode_t.
@@ -290,15 +291,17 @@ static bool CheckFileOperations()
res = false;
}
+ std::cerr << std::oct;
// Reset umask
-#if defined(_WIN32) && !defined(__CYGWIN__)
+#ifdef __MSYS__
+ mode_t fullMask = S_IWRITE;
+#elif defined(_WIN32) && !defined(__CYGWIN__)
// NOTE: Windows doesn't support toggling _S_IREAD.
mode_t fullMask = _S_IWRITE;
#else
// On a normal POSIX platform, we can toggle all permissions.
mode_t fullMask = S_IRWXU | S_IRWXG | S_IRWXO;
#endif
- mode_t orig_umask = umask(fullMask);
// Test file permissions without umask
mode_t origPerm, thisPerm;
@@ -329,9 +332,10 @@ static bool CheckFileOperations()
// While we're at it, check proper TestFileAccess functionality.
bool do_write_test = true;
-#if defined(__linux__)
- // If we are running as root on linux ignore this check, as
- // root can always write to files
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
+ defined(__NetBSD__) || defined(__DragonFly__)
+ // If we are running as root on POSIX-ish systems (Linux and the BSDs,
+ // at least), ignore this check, as root can always write to files.
do_write_test = (getuid() != 0);
#endif
if (do_write_test &&
@@ -370,6 +374,7 @@ static bool CheckFileOperations()
res = false;
}
+ mode_t orig_umask = umask(fullMask);
// Test setting file permissions while honoring umask
if (!kwsys::SystemTools::SetPermissions(testNewFile, fullMask, true)) {
std::cerr << "Problem with SetPermissions (3) for: " << testNewFile
@@ -422,21 +427,28 @@ static bool CheckFileOperations()
res = false;
}
-#if !defined(_WIN32)
std::string const testBadSymlink(testNewDir + "/badSymlink.txt");
std::string const testBadSymlinkTgt(testNewDir + "/missing/symlinkTgt.txt");
- if (!kwsys::SystemTools::CreateSymlink(testBadSymlinkTgt, testBadSymlink)) {
- std::cerr << "Problem with CreateSymlink for: " << testBadSymlink << " -> "
- << testBadSymlinkTgt << std::endl;
- res = false;
- }
+ kwsys::Status const symlinkStatus =
+ kwsys::SystemTools::CreateSymlink(testBadSymlinkTgt, testBadSymlink);
+#if defined(_WIN32)
+ // Under Windows, the user may not have enough privileges to create symlinks
+ if (symlinkStatus.GetWindows() != ERROR_PRIVILEGE_NOT_HELD)
+#endif
+ {
+ if (!symlinkStatus) {
+ std::cerr << "CreateSymlink for: " << testBadSymlink << " -> "
+ << testBadSymlinkTgt
+ << " failed: " << symlinkStatus.GetString() << std::endl;
+ res = false;
+ }
- if (!kwsys::SystemTools::Touch(testBadSymlink, false)) {
- std::cerr << "Problem with Touch (no create) for: " << testBadSymlink
- << std::endl;
- res = false;
+ if (!kwsys::SystemTools::Touch(testBadSymlink, false)) {
+ std::cerr << "Problem with Touch (no create) for: " << testBadSymlink
+ << std::endl;
+ res = false;
+ }
}
-#endif
if (!kwsys::SystemTools::Touch(testNewDir, false)) {
std::cerr << "Problem with Touch (no create) for: " << testNewDir
@@ -496,6 +508,7 @@ static bool CheckFileOperations()
}
#endif
+ std::cerr << std::dec;
return res;
}
@@ -1093,7 +1106,7 @@ static bool CheckCopyFileIfDifferent()
ret = false;
continue;
}
- std::string bdata = readFile("file_b");
+ std::string bdata = readFile(cptarget);
if (diff_test_cases[i].a != bdata) {
std::cerr << "Incorrect CopyFileIfDifferent file contents in test case "
<< i + 1 << "." << std::endl;
diff --git a/Templates/MSBuild/CustomBuildDepFile.targets b/Templates/MSBuild/CustomBuildDepFile.targets
new file mode 100644
index 000000000..2387ab539
--- /dev/null
+++ b/Templates/MSBuild/CustomBuildDepFile.targets
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!-- Update AdditionalInputs with depfile-discovered inputs. -->
+ <Target Name="CMakeCustomBuildDepFileAdditionalInputs" BeforeTargets="CustomBuild" Condition="'@(CustomBuild)' != ''">
+ <ItemGroup>
+ <!-- Save original AdditionalInputs generated by CMake. -->
+ <CustomBuild>
+ <CMakeAdditionalInputs>%(CustomBuild.AdditionalInputs)</CMakeAdditionalInputs>
+ </CustomBuild>
+ <!-- Read depfile-discovered inputs. -->
+ <CustomBuild Condition="Exists('%(CustomBuild.DepFileAdditionalInputsFile)')">
+ <DepFileAdditionalInputs>$([System.IO.File]::ReadAllText('%(CustomBuild.DepFileAdditionalInputsFile)').TrimEnd())</DepFileAdditionalInputs>
+ </CustomBuild>
+ <!-- Add depfile-discovered inputs to AdditionalInputs. -->
+ <CustomBuild Condition="'%(CustomBuild.DepFileAdditionalInputs)' != ''">
+ <AdditionalInputs Condition="'%(CustomBuild.AdditionalInputs)' == ''">%(CustomBuild.DepFileAdditionalInputs)</AdditionalInputs>
+ <AdditionalInputs Condition="'%(CustomBuild.AdditionalInputs)' != ''">%(CustomBuild.AdditionalInputs);%(CustomBuild.DepFileAdditionalInputs)</AdditionalInputs>
+ </CustomBuild>
+ </ItemGroup>
+ </Target>
+
+ <!-- Update the tracking log with depfile-discovered inputs. -->
+ <Target Name="CMakeCustomBuildDepFileTrackingLog" AfterTargets="CustomBuild" Condition="'@(CustomBuild)' != ''">
+ <!-- Compute the tracking log content for each CustomBuild item individually. -->
+ <ItemGroup>
+ <!-- Read depfile-discovered inputs. -->
+ <CustomBuild Condition="Exists('%(CustomBuild.DepFileAdditionalInputsFile)')">
+ <DepFileAdditionalInputs>$([System.IO.File]::ReadAllText('%(CustomBuild.DepFileAdditionalInputsFile)').TrimEnd())</DepFileAdditionalInputs>
+ </CustomBuild>
+ <!-- Generate tracking log representation of all inputs. -->
+ <CustomBuild>
+ <ReadTLog>^%(CustomBuild.Identity)&#xD;&#xA;</ReadTLog>
+ </CustomBuild>
+ <CustomBuild Condition="'%(CustomBuild.CMakeAdditionalInputs)' != ''">
+ <ReadTLog>%(ReadTLog)$([System.String]::Copy('%(CustomBuild.CMakeAdditionalInputs)').Trim(';').Replace(';', '&#xD;&#xA;'))&#xD;&#xA;</ReadTLog>
+ </CustomBuild>
+ <CustomBuild Condition="'%(CustomBuild.DepFileAdditionalInputs)' != ''">
+ <ReadTLog>%(ReadTLog)$([System.String]::Copy('%(CustomBuild.DepFileAdditionalInputs)').Trim(';').Replace(';', '&#xD;&#xA;'))&#xD;&#xA;</ReadTLog>
+ </CustomBuild>
+ </ItemGroup>
+ <!-- Compute the combined tracking log for all CustomBuild items together. -->
+ <PropertyGroup>
+ <CustomBuildReadTLog>@(CustomBuild->'%(ReadTLog)','')</CustomBuildReadTLog>
+ </PropertyGroup>
+ <!-- Replace the combined tracking log on disk. -->
+ <WriteLinesToFile File="$(TLogLocation)CustomBuild.read.1.tlog" Overwrite="true" Lines="$(CustomBuildReadTLog.ToUpper())" />
+ </Target>
+</Project>
diff --git a/Templates/MSBuild/FlagTables/v10_CSharp.json b/Templates/MSBuild/FlagTables/v10_CSharp.json
index 5989aea1e..9f21d9a27 100644
--- a/Templates/MSBuild/FlagTables/v10_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v10_CSharp.json
@@ -363,52 +363,13 @@
},
{
"name": "LangVersion",
- "switch": "langversion:ISO-1",
+ "switch": "langversion:",
"comment": "",
- "value": "ISO-1",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:ISO-2",
- "comment": "",
- "value": "ISO-2",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:3",
- "comment": "",
- "value": "3",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:4",
- "comment": "",
- "value": "4",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:5",
- "comment": "",
- "value": "5",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:6",
- "comment": "",
- "value": "6",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:default",
- "comment": "",
- "value": "default",
- "flags": []
+ "value": "",
+ "flags": [
+ "UserValue",
+ "UserRequired"
+ ]
},
{
"name": "DelaySign",
diff --git a/Templates/MSBuild/FlagTables/v10_Link.json b/Templates/MSBuild/FlagTables/v10_Link.json
index ac5b8b16c..494774bc2 100644
--- a/Templates/MSBuild/FlagTables/v10_Link.json
+++ b/Templates/MSBuild/FlagTables/v10_Link.json
@@ -1090,15 +1090,6 @@
]
},
{
- "name": "MergeSections",
- "switch": "MERGE:",
- "comment": "Merge Sections",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
"name": "LinkKeyFile",
"switch": "KEYFILE:",
"comment": "Key File",
diff --git a/Templates/MSBuild/FlagTables/v11_CSharp.json b/Templates/MSBuild/FlagTables/v11_CSharp.json
index 5989aea1e..9f21d9a27 100644
--- a/Templates/MSBuild/FlagTables/v11_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v11_CSharp.json
@@ -363,52 +363,13 @@
},
{
"name": "LangVersion",
- "switch": "langversion:ISO-1",
+ "switch": "langversion:",
"comment": "",
- "value": "ISO-1",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:ISO-2",
- "comment": "",
- "value": "ISO-2",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:3",
- "comment": "",
- "value": "3",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:4",
- "comment": "",
- "value": "4",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:5",
- "comment": "",
- "value": "5",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:6",
- "comment": "",
- "value": "6",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:default",
- "comment": "",
- "value": "default",
- "flags": []
+ "value": "",
+ "flags": [
+ "UserValue",
+ "UserRequired"
+ ]
},
{
"name": "DelaySign",
diff --git a/Templates/MSBuild/FlagTables/v11_Link.json b/Templates/MSBuild/FlagTables/v11_Link.json
index 5d5c13f21..0db5d9e05 100644
--- a/Templates/MSBuild/FlagTables/v11_Link.json
+++ b/Templates/MSBuild/FlagTables/v11_Link.json
@@ -1225,15 +1225,6 @@
]
},
{
- "name": "MergeSections",
- "switch": "MERGE:",
- "comment": "Merge Sections",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
"name": "LinkKeyFile",
"switch": "KEYFILE:",
"comment": "Key File",
diff --git a/Templates/MSBuild/FlagTables/v12_CSharp.json b/Templates/MSBuild/FlagTables/v12_CSharp.json
index 5989aea1e..9f21d9a27 100644
--- a/Templates/MSBuild/FlagTables/v12_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v12_CSharp.json
@@ -363,52 +363,13 @@
},
{
"name": "LangVersion",
- "switch": "langversion:ISO-1",
+ "switch": "langversion:",
"comment": "",
- "value": "ISO-1",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:ISO-2",
- "comment": "",
- "value": "ISO-2",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:3",
- "comment": "",
- "value": "3",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:4",
- "comment": "",
- "value": "4",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:5",
- "comment": "",
- "value": "5",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:6",
- "comment": "",
- "value": "6",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:default",
- "comment": "",
- "value": "default",
- "flags": []
+ "value": "",
+ "flags": [
+ "UserValue",
+ "UserRequired"
+ ]
},
{
"name": "DelaySign",
diff --git a/Templates/MSBuild/FlagTables/v12_Link.json b/Templates/MSBuild/FlagTables/v12_Link.json
index 5d5c13f21..0db5d9e05 100644
--- a/Templates/MSBuild/FlagTables/v12_Link.json
+++ b/Templates/MSBuild/FlagTables/v12_Link.json
@@ -1225,15 +1225,6 @@
]
},
{
- "name": "MergeSections",
- "switch": "MERGE:",
- "comment": "Merge Sections",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
"name": "LinkKeyFile",
"switch": "KEYFILE:",
"comment": "Key File",
diff --git a/Templates/MSBuild/FlagTables/v140_CSharp.json b/Templates/MSBuild/FlagTables/v140_CSharp.json
index 5989aea1e..9f21d9a27 100644
--- a/Templates/MSBuild/FlagTables/v140_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v140_CSharp.json
@@ -363,52 +363,13 @@
},
{
"name": "LangVersion",
- "switch": "langversion:ISO-1",
+ "switch": "langversion:",
"comment": "",
- "value": "ISO-1",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:ISO-2",
- "comment": "",
- "value": "ISO-2",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:3",
- "comment": "",
- "value": "3",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:4",
- "comment": "",
- "value": "4",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:5",
- "comment": "",
- "value": "5",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:6",
- "comment": "",
- "value": "6",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:default",
- "comment": "",
- "value": "default",
- "flags": []
+ "value": "",
+ "flags": [
+ "UserValue",
+ "UserRequired"
+ ]
},
{
"name": "DelaySign",
diff --git a/Templates/MSBuild/FlagTables/v140_Link.json b/Templates/MSBuild/FlagTables/v140_Link.json
index 3fb072c50..7e293b140 100644
--- a/Templates/MSBuild/FlagTables/v140_Link.json
+++ b/Templates/MSBuild/FlagTables/v140_Link.json
@@ -1269,15 +1269,6 @@
]
},
{
- "name": "MergeSections",
- "switch": "MERGE:",
- "comment": "Merge Sections",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
"name": "LinkKeyFile",
"switch": "KEYFILE:",
"comment": "Key File",
diff --git a/Templates/MSBuild/FlagTables/v141_CL.json b/Templates/MSBuild/FlagTables/v141_CL.json
index 01fafe48d..5b18e32ea 100644
--- a/Templates/MSBuild/FlagTables/v141_CL.json
+++ b/Templates/MSBuild/FlagTables/v141_CL.json
@@ -421,8 +421,29 @@
},
{
"name": "SpectreMitigation",
+ "switch": "Qspectre-load-cf",
+ "comment": "All Control Flow Loads",
+ "value": "SpectreLoadCF",
+ "flags": []
+ },
+ {
+ "name": "SpectreMitigation",
+ "switch": "Qspectre-load",
+ "comment": "All Loads",
+ "value": "SpectreLoad",
+ "flags": []
+ },
+ {
+ "name": "SpectreMitigation",
+ "switch": "Qspectre-",
+ "comment": "Disabled",
+ "value": "false",
+ "flags": []
+ },
+ {
+ "name": "SpectreMitigation",
"switch": "Qspectre",
- "comment": "Spectre mitigations",
+ "comment": "Enabled",
"value": "Spectre",
"flags": []
},
@@ -589,6 +610,20 @@
"flags": []
},
{
+ "name": "SupportJustMyCode",
+ "switch": "JMC-",
+ "comment": "",
+ "value": "false",
+ "flags": []
+ },
+ {
+ "name": "SupportJustMyCode",
+ "switch": "JMC",
+ "comment": "",
+ "value": "true",
+ "flags": []
+ },
+ {
"name": "CompileAsWinRT",
"switch": "ZW",
"comment": "Consume Windows Runtime Extension",
@@ -812,7 +847,7 @@
{
"name": "ConformanceMode",
"switch": "permissive-",
- "comment": "Conformance mode enabled",
+ "comment": "Conformance mode",
"value": "true",
"flags": []
},
@@ -1250,19 +1285,5 @@
"comment": "C++14 (GNU Dialect)",
"value": "gnu++1y",
"flags": []
- },
- {
- "name": "SupportJustMyCode",
- "switch": "JMC-",
- "comment": "",
- "value": "false",
- "flags": []
- },
- {
- "name": "SupportJustMyCode",
- "switch": "JMC",
- "comment": "",
- "value": "true",
- "flags": []
}
]
diff --git a/Templates/MSBuild/FlagTables/v141_CSharp.json b/Templates/MSBuild/FlagTables/v141_CSharp.json
index 5989aea1e..9f21d9a27 100644
--- a/Templates/MSBuild/FlagTables/v141_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v141_CSharp.json
@@ -363,52 +363,13 @@
},
{
"name": "LangVersion",
- "switch": "langversion:ISO-1",
+ "switch": "langversion:",
"comment": "",
- "value": "ISO-1",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:ISO-2",
- "comment": "",
- "value": "ISO-2",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:3",
- "comment": "",
- "value": "3",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:4",
- "comment": "",
- "value": "4",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:5",
- "comment": "",
- "value": "5",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:6",
- "comment": "",
- "value": "6",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:default",
- "comment": "",
- "value": "default",
- "flags": []
+ "value": "",
+ "flags": [
+ "UserValue",
+ "UserRequired"
+ ]
},
{
"name": "DelaySign",
diff --git a/Templates/MSBuild/FlagTables/v141_Link.json b/Templates/MSBuild/FlagTables/v141_Link.json
index 66ee76fcb..e311240b6 100644
--- a/Templates/MSBuild/FlagTables/v141_Link.json
+++ b/Templates/MSBuild/FlagTables/v141_Link.json
@@ -1276,15 +1276,6 @@
]
},
{
- "name": "MergeSections",
- "switch": "MERGE:",
- "comment": "Merge Sections",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
"name": "LinkKeyFile",
"switch": "KEYFILE:",
"comment": "Key File",
diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json
index 3305e5643..49776d0fe 100644
--- a/Templates/MSBuild/FlagTables/v142_CL.json
+++ b/Templates/MSBuild/FlagTables/v142_CL.json
@@ -386,6 +386,13 @@
},
{
"name": "EnableEnhancedInstructionSet",
+ "switch": "arch:AVX512",
+ "comment": "Advanced Vector Extensions 512",
+ "value": "AdvancedVectorExtensions512",
+ "flags": []
+ },
+ {
+ "name": "EnableEnhancedInstructionSet",
"switch": "arch:IA32",
"comment": "No Enhanced Instructions",
"value": "NoExtensions",
@@ -421,19 +428,47 @@
},
{
"name": "SpectreMitigation",
+ "switch": "Qspectre-load-cf",
+ "comment": "All Control Flow Loads",
+ "value": "SpectreLoadCF",
+ "flags": []
+ },
+ {
+ "name": "SpectreMitigation",
+ "switch": "Qspectre-load",
+ "comment": "All Loads",
+ "value": "SpectreLoad",
+ "flags": []
+ },
+ {
+ "name": "SpectreMitigation",
"switch": "Qspectre-",
- "comment": "Spectre mitigations disabled",
+ "comment": "Disabled",
"value": "false",
"flags": []
},
{
"name": "SpectreMitigation",
"switch": "Qspectre",
- "comment": "Spectre mitigations enabled",
+ "comment": "Enabled",
"value": "Spectre",
"flags": []
},
{
+ "name": "ConformanceMode",
+ "switch": "permissive-",
+ "comment": "Yes",
+ "value": "true",
+ "flags": []
+ },
+ {
+ "name": "ConformanceMode",
+ "switch": "permissive",
+ "comment": "No",
+ "value": "false",
+ "flags": []
+ },
+ {
"name": "LanguageStandard",
"switch": "std:c++14",
"comment": "ISO C++14 Standard",
@@ -442,6 +477,13 @@
},
{
"name": "LanguageStandard",
+ "switch": "std:c++20",
+ "comment": "ISO C++20 Standard",
+ "value": "stdcpp20",
+ "flags": []
+ },
+ {
+ "name": "LanguageStandard",
"switch": "std:c++17",
"comment": "ISO C++17 Standard",
"value": "stdcpp17",
@@ -537,6 +579,7 @@
"switch": "external:W0",
"comment": "Turn Off All Warnings",
"value": "TurnOffAllWarnings",
+ "vsmin": "16.10.31321.278",
"flags": []
},
{
@@ -544,6 +587,7 @@
"switch": "external:W1",
"comment": "Level1",
"value": "Level1",
+ "vsmin": "16.10.31321.278",
"flags": []
},
{
@@ -551,6 +595,7 @@
"switch": "external:W2",
"comment": "Level2",
"value": "Level2",
+ "vsmin": "16.10.31321.278",
"flags": []
},
{
@@ -558,6 +603,7 @@
"switch": "external:W3",
"comment": "Level3",
"value": "Level3",
+ "vsmin": "16.10.31321.278",
"flags": []
},
{
@@ -565,6 +611,7 @@
"switch": "external:W4",
"comment": "Level4",
"value": "Level4",
+ "vsmin": "16.10.31321.278",
"flags": []
},
{
@@ -617,6 +664,27 @@
"flags": []
},
{
+ "name": "CompileAs",
+ "switch": "interface",
+ "comment": "Compile as C++ Module Code",
+ "value": "CompileAsCppModule",
+ "flags": []
+ },
+ {
+ "name": "CompileAs",
+ "switch": "internalPartition",
+ "comment": "Compile as C++ Module Internal Partition",
+ "value": "CompileAsCppModuleInternalPartition",
+ "flags": []
+ },
+ {
+ "name": "CompileAs",
+ "switch": "exportHeader",
+ "comment": "Compile as C++ Header Unit",
+ "value": "CompileAsHeaderUnit",
+ "flags": []
+ },
+ {
"name": "ErrorReporting",
"switch": "errorReport:none",
"comment": "Do Not Send Report",
@@ -719,6 +787,13 @@
]
},
{
+ "name": "ForceSynchronousPDBWrites",
+ "switch": "FS",
+ "comment": "Force Synchronous PDB Writes",
+ "value": "true",
+ "flags": []
+ },
+ {
"name": "IntrinsicFunctions",
"switch": "Oi",
"comment": "Enable Intrinsic Functions",
@@ -789,6 +864,20 @@
"flags": []
},
{
+ "name": "UseStandardPreprocessor",
+ "switch": "Zc:preprocessor-",
+ "comment": "Use Standard Conforming Preprocessor",
+ "value": "false",
+ "flags": []
+ },
+ {
+ "name": "UseStandardPreprocessor",
+ "switch": "Zc:preprocessor",
+ "comment": "Use Standard Conforming Preprocessor",
+ "value": "true",
+ "flags": []
+ },
+ {
"name": "StringPooling",
"switch": "GF-",
"comment": "Enable String Pooling",
@@ -873,27 +962,48 @@
"flags": []
},
{
- "name": "DisableLanguageExtensions",
- "switch": "Za",
- "comment": "Disable Language Extensions",
+ "name": "IntelJCCErratum",
+ "switch": "QIntel-jcc-erratum",
+ "comment": "Enable Intel JCC Erratum Mitigation",
"value": "true",
"flags": []
},
{
- "name": "ConformanceMode",
- "switch": "permissive-",
- "comment": "Conformance mode enabled",
+ "name": "GuardEHContMetadata",
+ "switch": "guard:ehcont-",
+ "comment": "Enable EH Continuation Metadata",
+ "value": "false",
+ "flags": []
+ },
+ {
+ "name": "GuardEHContMetadata",
+ "switch": "guard:ehcont",
+ "comment": "Enable EH Continuation Metadata",
"value": "true",
"flags": []
},
{
- "name": "ConformanceMode",
- "switch": "permissive",
- "comment": "Conformance mode disabled",
+ "name": "GuardSignedReturns",
+ "switch": "guard:signret-",
+ "comment": "Enable Signed Returns",
"value": "false",
"flags": []
},
{
+ "name": "GuardSignedReturns",
+ "switch": "guard:signret",
+ "comment": "Enable Signed Returns",
+ "value": "true",
+ "flags": []
+ },
+ {
+ "name": "DisableLanguageExtensions",
+ "switch": "Za",
+ "comment": "Disable Language Extensions",
+ "value": "true",
+ "flags": []
+ },
+ {
"name": "TreatWChar_tAsBuiltInType",
"switch": "Zc:wchar_t-",
"comment": "Treat WChar_t As Built in Type",
@@ -980,7 +1090,7 @@
{
"name": "EnableModules",
"switch": "experimental:module",
- "comment": "Enable C++ Modules (experimental)",
+ "comment": "Enable Experimental C++ Standard Library Modules",
"value": "true",
"flags": []
},
@@ -999,6 +1109,15 @@
"flags": []
},
{
+ "name": "GenerateModuleDependencies",
+ "switch": "sourceDependencies:directives",
+ "comment": "Generate Module Dependenices File",
+ "value": "true",
+ "flags": [
+ "Continue"
+ ]
+ },
+ {
"name": "GenerateXMLDocumentationFiles",
"switch": "doc",
"comment": "Generate XML Documentation Files",
@@ -1010,6 +1129,15 @@
]
},
{
+ "name": "GenerateSourceDependencies",
+ "switch": "sourceDependencies",
+ "comment": "Generate Source Dependencies File",
+ "value": "true",
+ "flags": [
+ "Continue"
+ ]
+ },
+ {
"name": "BrowseInformation",
"switch": "FR",
"comment": "Enable Browse Information",
@@ -1021,6 +1149,29 @@
]
},
{
+ "name": "TreatAngleIncludeAsExternal",
+ "switch": "external:anglebrackets",
+ "comment": "Treat Files Included with Angle Brackets as External",
+ "value": "true",
+ "vsmin": "16.10.31321.278",
+ "flags": []
+ },
+ {
+ "name": "ExternalTemplatesDiagnostics",
+ "switch": "external:templates-",
+ "comment": "Template Diagnostics in External Headers",
+ "value": "true",
+ "vsmin": "16.10.31321.278",
+ "flags": []
+ },
+ {
+ "name": "DisableAnalyzeExternal",
+ "switch": "analyze:external-",
+ "comment": "Disable Code Analysis for External Headers",
+ "value": "true",
+ "flags": []
+ },
+ {
"name": "ShowIncludes",
"switch": "showIncludes",
"comment": "Show Includes",
@@ -1076,6 +1227,36 @@
]
},
{
+ "name": "AdditionalBMIDirectories",
+ "switch": "ifcSearchDir",
+ "comment": "Additional BMI Directories",
+ "value": "",
+ "flags": [
+ "UserValue",
+ "SemicolonAppendable"
+ ]
+ },
+ {
+ "name": "AdditionalModuleDependencies",
+ "switch": "reference",
+ "comment": "Additional Module Dependencies",
+ "value": "",
+ "flags": [
+ "UserValue",
+ "SemicolonAppendable"
+ ]
+ },
+ {
+ "name": "AdditionalHeaderUnitDependencies",
+ "switch": "headerUnit",
+ "comment": "Additional Header Unit Dependencies",
+ "value": "",
+ "flags": [
+ "UserValue",
+ "SemicolonAppendable"
+ ]
+ },
+ {
"name": "PreprocessorDefinitions",
"switch": "D",
"comment": "Preprocessor Definitions",
@@ -1096,6 +1277,27 @@
]
},
{
+ "name": "StdIfcDirectory",
+ "switch": "stdIfcDir",
+ "comment": "",
+ "value": "",
+ "flags": [
+ "UserValue",
+ "SemicolonAppendable"
+ ]
+ },
+ {
+ "name": "ExternalDirectoriesEnv",
+ "switch": "external:env:",
+ "comment": "External Directories Environment Variables",
+ "value": "",
+ "vsmin": "16.10.31321.278",
+ "flags": [
+ "UserValue",
+ "SemicolonAppendable"
+ ]
+ },
+ {
"name": "DisableSpecificWarnings",
"switch": "wd",
"comment": "Disable Specific Warnings",
@@ -1211,6 +1413,24 @@
]
},
{
+ "name": "ModuleOutputFile",
+ "switch": "ifcOutput",
+ "comment": "Module Output File Name",
+ "value": "",
+ "flags": [
+ "UserValue"
+ ]
+ },
+ {
+ "name": "ModuleDependenciesFile",
+ "switch": "sourceDependencies:directives",
+ "comment": "Module Dependencies File Name",
+ "value": "",
+ "flags": [
+ "UserFollowing"
+ ]
+ },
+ {
"name": "ObjectFileName",
"switch": "Fo",
"comment": "Object File Name",
@@ -1239,6 +1459,15 @@
]
},
{
+ "name": "SourceDependenciesFile",
+ "switch": "sourceDependencies",
+ "comment": "Source Dependencies File Name",
+ "value": "",
+ "flags": [
+ "UserFollowing"
+ ]
+ },
+ {
"name": "BrowseInformationFile",
"switch": "FR",
"comment": "Browse Information File",
diff --git a/Templates/MSBuild/FlagTables/v142_CSharp.json b/Templates/MSBuild/FlagTables/v142_CSharp.json
index 4dcea9de3..ae1bd47bf 100644
--- a/Templates/MSBuild/FlagTables/v142_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v142_CSharp.json
@@ -381,52 +381,13 @@
},
{
"name": "LangVersion",
- "switch": "langversion:ISO-1",
+ "switch": "langversion:",
"comment": "",
- "value": "ISO-1",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:ISO-2",
- "comment": "",
- "value": "ISO-2",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:3",
- "comment": "",
- "value": "3",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:4",
- "comment": "",
- "value": "4",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:5",
- "comment": "",
- "value": "5",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:6",
- "comment": "",
- "value": "6",
- "flags": []
- },
- {
- "name": "LangVersion",
- "switch": "langversion:default",
- "comment": "",
- "value": "default",
- "flags": []
+ "value": "",
+ "flags": [
+ "UserValue",
+ "UserRequired"
+ ]
},
{
"name": "DelaySign",
diff --git a/Templates/MSBuild/FlagTables/v142_Link.json b/Templates/MSBuild/FlagTables/v142_Link.json
index 110dcc2b1..d5fc2e4d7 100644
--- a/Templates/MSBuild/FlagTables/v142_Link.json
+++ b/Templates/MSBuild/FlagTables/v142_Link.json
@@ -1283,15 +1283,6 @@
]
},
{
- "name": "MergeSections",
- "switch": "MERGE:",
- "comment": "Merge Sections",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
"name": "LinkKeyFile",
"switch": "KEYFILE:",
"comment": "Key File",
diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in
index 3e47d6a0d..61134172e 100644
--- a/Templates/TestDriver.cxx.in
+++ b/Templates/TestDriver.cxx.in
@@ -2,6 +2,7 @@
#include <stdio.h> /* NOLINT */
#include <stdlib.h> /* NOLINT */
#include <string.h> /* NOLINT */
+#include <time.h>
#if defined(_MSC_VER)
#pragma warning(disable : 4996) /* deprecation */
@@ -62,11 +63,23 @@ static char* lowercase(const char* string)
return new_string;
}
+int isTestSkipped(const char *name, int n_skipped_tests, char *skipped_tests[]) {
+ int i;
+ for (i = 0; i < n_skipped_tests; i++) {
+ if (strcmp(name, skipped_tests[i]) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
int main(int ac, char* av[])
{
int i;
int testNum = 0;
int partial_match;
+ int run_all;
char *arg;
int testToRun = -1;
@@ -95,15 +108,45 @@ int main(int ac, char* av[])
av++;
}
partial_match = 0;
+ run_all = 0;
arg = CM_NULL; /* NOLINT */
- /* If partial match is requested. */
+ /* If partial match or running all tests are requested. */
if (testToRun == -1 && ac > 1) {
partial_match = (strcmp(av[1], "-R") == 0) ? 1 : 0;
+ run_all = (strcmp(av[1], "-A") == 0) ? 1 : 0;
}
if (partial_match != 0 && ac < 3) {
printf("-R needs an additional parameter.\n");
return -1;
}
+ if (run_all == 1) {
+ clock_t t;
+ int status = 0;
+ const char* status_message = NULL;
+ printf("TAP version 13\n");
+ printf("1..%d\n", NumTests);
+ for (i = 0; i < NumTests; ++i) {
+ const char *name = cmakeGeneratedFunctionMapEntries[i].name;
+ if (ac > 2) {
+ if (isTestSkipped(name, ac - 2, av + 2) == 1) {
+ printf("ok %d %s # SKIP\n", i + 1, name);
+ continue;
+ }
+ }
+ t = clock();
+ status = (*cmakeGeneratedFunctionMapEntries[i].func)(ac, av);
+ t = clock() - t;
+ status_message = (status == -1) ? "not ok" : "ok";
+ {
+ double time_taken = ((double)t) / CLOCKS_PER_SEC;
+ printf("%s %d %s # %f\n", status_message, i + 1, name, time_taken);
+ }
+ }
+ printf("All tests finished.\n");
+
+ return 0;
+ }
+
if (testToRun == -1) {
arg = lowercase(av[1 + partial_match]);
}
diff --git a/Tests/BundleGeneratorTest/CMakeLists.txt b/Tests/BundleGeneratorTest/CMakeLists.txt
index 037df09c1..cf7e2ce86 100644
--- a/Tests/BundleGeneratorTest/CMakeLists.txt
+++ b/Tests/BundleGeneratorTest/CMakeLists.txt
@@ -1,6 +1,6 @@
project(BundleGeneratorTest)
-cmake_minimum_required(VERSION 2.7)
+cmake_minimum_required(VERSION 2.8.12)
# Build a shared library and install it in lib/
add_library(Library SHARED Library.cxx)
diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
index aa8e21a68..07ec4e32d 100644
--- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
@@ -140,6 +140,8 @@ cmake_policy(PUSH)
cmake_policy(SET CMP0022 NEW)
cmake_policy(SET CMP0079 NEW)
add_executable(TopDir TopDir.c)
+add_library(TopDirInterface INTERFACE)
+target_link_libraries(TopDir PRIVATE TopDirInterface)
add_subdirectory(SubDirA)
add_subdirectory(SubDirB)
target_link_libraries(SubDirB TopDirImported)
diff --git a/Tests/CMakeCommands/target_link_libraries/SubDirA/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/SubDirA/CMakeLists.txt
index 4dae10395..df7c483c6 100644
--- a/Tests/CMakeCommands/target_link_libraries/SubDirA/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/SubDirA/CMakeLists.txt
@@ -3,6 +3,8 @@ add_executable(SubDirA SubDirA.c)
# Link to a target imported in this directory that would not normally
# be visible to the directory in which TopDir is defined.
target_link_libraries(TopDir PUBLIC SameNameImported)
+# Do the same through an interface library in the top.
+target_link_libraries(TopDirInterface INTERFACE SameNameImported2)
# Link SubDirA to a target imported in this directory that has the same
# name as a target imported in SubDirB's directory. SubDirB will also
@@ -13,3 +15,5 @@ target_link_libraries(SubDirA PRIVATE SameNameImported)
# Distinguish this copy by having a unique usage requirement.
add_library(SameNameImported IMPORTED INTERFACE)
target_compile_definitions(SameNameImported INTERFACE DEF_SameNameImportedSubDirA)
+add_library(SameNameImported2 INTERFACE IMPORTED)
+target_compile_definitions(SameNameImported2 INTERFACE DEF_SameNameImported2SubDirA)
diff --git a/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt
index 06d111104..9af577c01 100644
--- a/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt
@@ -3,6 +3,8 @@ add_executable(SubDirB SubDirB.c)
# Link to a target imported in this directory that would not normally
# be visible to the directory in which TopDir is defined.
target_link_libraries(TopDir PUBLIC debug SameNameImported optimized SameNameImported)
+# Do the same through an interface library in the top.
+target_link_libraries(TopDirInterface INTERFACE debug SameNameImported2 optimized SameNameImported2)
# Link to a list of targets imported in this directory that would not
# normally be visible to the directory in which TopDir is defined.
@@ -17,3 +19,5 @@ target_link_libraries(SubDirA PRIVATE SameNameImported)
# Distinguish this copy by having a unique usage requirement.
add_library(SameNameImported IMPORTED INTERFACE)
target_compile_definitions(SameNameImported INTERFACE DEF_SameNameImportedSubDirB)
+add_library(SameNameImported2 INTERFACE IMPORTED)
+target_compile_definitions(SameNameImported2 INTERFACE DEF_SameNameImported2SubDirB)
diff --git a/Tests/CMakeCommands/target_link_libraries/TopDir.c b/Tests/CMakeCommands/target_link_libraries/TopDir.c
index d8066e5ca..708b5c1fa 100644
--- a/Tests/CMakeCommands/target_link_libraries/TopDir.c
+++ b/Tests/CMakeCommands/target_link_libraries/TopDir.c
@@ -4,6 +4,12 @@
#ifndef DEF_SameNameImportedSubDirB
# error "DEF_SameNameImportedSubDirB is not defined but should be!"
#endif
+#ifndef DEF_SameNameImported2SubDirA
+# error "DEF_SameNameImported2SubDirA is not defined but should be!"
+#endif
+#ifndef DEF_SameNameImported2SubDirB
+# error "DEF_SameNameImported2SubDirB is not defined but should be!"
+#endif
#ifdef DEF_TopDirImported
# error "DEF_TopDirImported is defined but should not be!"
#endif
diff --git a/Tests/CMakeLib/testOptional.cxx b/Tests/CMakeLib/testOptional.cxx
index 2d7dd7c68..9d4b72aa4 100644
--- a/Tests/CMakeLib/testOptional.cxx
+++ b/Tests/CMakeLib/testOptional.cxx
@@ -301,12 +301,14 @@ static bool testMoveConstruct(std::vector<Event>& expected)
cm::optional<EventLogger> o3{};
const cm::optional<EventLogger> o4{ std::move(o3) };
+#ifndef __clang_analyzer__ /* cplusplus.Move */
expected = {
{ Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 },
{ Event::MOVE_CONSTRUCT, &*o2, &*o1, 4 },
{ Event::DESTRUCT, &*o2, nullptr, 4 },
{ Event::DESTRUCT, &*o1, nullptr, 4 },
};
+#endif
return true;
}
diff --git a/Tests/CMakeLib/testString.cxx b/Tests/CMakeLib/testString.cxx
index ad800cf06..5a9cad18b 100644
--- a/Tests/CMakeLib/testString.cxx
+++ b/Tests/CMakeLib/testString.cxx
@@ -326,12 +326,14 @@ static bool testConstructMove()
std::cout << "testConstructMove()\n";
cm::String s1 = std::string("abc");
cm::String s2 = std::move(s1);
+#ifndef __clang_analyzer__ /* cplusplus.Move */
ASSERT_TRUE(s1.data() == nullptr);
ASSERT_TRUE(s1.size() == 0);
ASSERT_TRUE(s2.size() == 3);
ASSERT_TRUE(std::strncmp(s2.data(), "abc", 3) == 0);
ASSERT_TRUE(s1.is_stable());
ASSERT_TRUE(s2.is_stable());
+#endif
return true;
}
@@ -356,12 +358,14 @@ static bool testAssignMove()
cm::String s1 = std::string("abc");
cm::String s2;
s2 = std::move(s1);
+#ifndef __clang_analyzer__ /* cplusplus.Move */
ASSERT_TRUE(s1.data() == nullptr);
ASSERT_TRUE(s1.size() == 0);
ASSERT_TRUE(s2.size() == 3);
ASSERT_TRUE(std::strncmp(s2.data(), "abc", 3) == 0);
ASSERT_TRUE(s1.is_stable());
ASSERT_TRUE(s2.is_stable());
+#endif
return true;
}
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser.cxx b/Tests/CMakeLib/testVisualStudioSlnParser.cxx
index 3c069600c..7fdba9a2a 100644
--- a/Tests/CMakeLib/testVisualStudioSlnParser.cxx
+++ b/Tests/CMakeLib/testVisualStudioSlnParser.cxx
@@ -33,7 +33,7 @@ int testVisualStudioSlnParser(int, char* [])
// Test clean parser
if (parser.GetParseResult() != cmVisualStudioSlnParser::ResultOK) {
- std::cerr << "cmVisualStudioSlnParser initialisation failed" << std::endl;
+ std::cerr << "cmVisualStudioSlnParser initialization failed" << std::endl;
return 1;
}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index bb83feab4..341aba635 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -25,14 +25,14 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/CheckFortran.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/CheckSwift.cmake)
# Fake a user home directory to avoid polluting the real one.
-if(DEFINED ENV{HOME} AND NOT CTEST_NO_TEST_HOME)
+if(NOT CTEST_NO_TEST_HOME AND (NOT WIN32 OR DEFINED ENV{HOME}))
set(TEST_HOME "${CMake_BINARY_DIR}/Tests/CMakeFiles/TestHome")
file(MAKE_DIRECTORY "${TEST_HOME}")
file(WRITE "${TEST_HOME}/.cvspass" ":pserver:anoncvs@www.cmake.org:/cvsroot/KWSys A\n")
set(TEST_HOME_ENV_CODE "# Fake a user home directory to avoid polluting the real one.
# But provide original ENV{HOME} value in ENV{CTEST_REAL_HOME} for tests that
# need access to the real HOME directory.
-if(NOT DEFINED ENV{CTEST_REAL_HOME})
+if(DEFINED ENV{HOME} AND NOT DEFINED ENV{CTEST_REAL_HOME})
set(ENV{CTEST_REAL_HOME} \"\$ENV{HOME}\")
endif()
set(ENV{HOME} \"${TEST_HOME}\")
@@ -96,7 +96,7 @@ if(BUILD_TESTING)
# some old versions of make simply cannot handle spaces in paths
if (MAKE_IS_GNU OR
CMAKE_MAKE_PROGRAM MATCHES "nmake|gmake|wmake" OR
- CMAKE_GENERATOR MATCHES "Visual Studio|Xcode|Borland")
+ CMAKE_GENERATOR MATCHES "Visual Studio|Xcode|Borland|Ninja")
set(MAKE_SUPPORTS_SPACES 1)
else()
set(MAKE_SUPPORTS_SPACES 0)
@@ -209,9 +209,12 @@ if(BUILD_TESTING)
if(CMAKE_HOST_WIN32 AND COMMAND cmake_host_system_information)
set(info_vs15 "VS_15_DIR")
set(info_vs16 "VS_16_DIR")
+ set(info_vs17 "VS_17_DIR")
set(vs_versions)
if(WIN32)
- if(NOT CMAKE_VERSION VERSION_LESS 3.14)
+ if(NOT CMAKE_VERSION VERSION_LESS 3.21.20210624)
+ set(vs_versions vs15 vs16 vs17)
+ elseif(NOT CMAKE_VERSION VERSION_LESS 3.14)
set(vs_versions vs15 vs16)
elseif(NOT CMAKE_VERSION VERSION_LESS 3.8)
set(vs_versions vs15)
@@ -460,7 +463,7 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(OutName exe.OutName.exe)
ADD_TEST_MACRO(ObjectLibrary UseCshared)
ADD_TEST_MACRO(NewlineArgs NewlineArgs)
- ADD_TEST_MACRO(SetLang SetLang)
+ ADD_TEST_MACRO(SetLang SetLangX)
ADD_TEST_MACRO(EmptyProperty EmptyProperty)
ADD_TEST_MACRO(ExternalOBJ ExternalOBJ)
if(NOT CMake_TEST_EXTERNAL_CMAKE)
@@ -478,6 +481,7 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(Preprocess Preprocess)
set(ExportImport_BUILD_OPTIONS -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}
-DCMake_TEST_CUDA:BOOL=${CMake_TEST_CUDA}
+ -DCMake_INSTALL_NAME_TOOL_BUG:BOOL=${CMake_INSTALL_NAME_TOOL_BUG}
)
ADD_TEST_MACRO(ExportImport ExportImport)
set_property(TEST ExportImport APPEND
@@ -489,6 +493,11 @@ if(BUILD_TESTING)
if(CMAKE_Fortran_COMPILER)
set(CompileOptions_BUILD_OPTIONS -DTEST_FORTRAN=1)
endif()
+ if(_isMultiConfig)
+ set(CompileOptions_CTEST_OPTIONS --build-config $<CONFIGURATION>)
+ else()
+ set(CompileOptions_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=$<CONFIGURATION>)
+ endif()
ADD_TEST_MACRO(CompileOptions CompileOptions)
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
ADD_TEST_MACRO(AliasTarget AliasTarget)
@@ -532,7 +541,7 @@ if(BUILD_TESTING)
if(CTEST_TEST_OSX_ARCH)
ADD_TEST_MACRO(Architecture Architecture)
set_tests_properties(Architecture PROPERTIES
- PASS_REGULAR_EXPRESSION "(file is not of required architecture|does not match cputype|not the architecture being linked)")
+ PASS_REGULAR_EXPRESSION "(file is not of required architecture|does not match cputype|not the architecture being linked|but attempting to link with file built for)")
endif()
list(APPEND TEST_BUILD_DIRS ${CMake_TEST_INSTALL_PREFIX})
@@ -804,6 +813,7 @@ if(BUILD_TESTING)
${build_generator_args}
--build-project Framework
--build-options
+ -DMAKE_SUPPORTS_SPACES=${MAKE_SUPPORTS_SPACES}
"-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/Framework/Install"
--test-command bar)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Framework")
@@ -828,6 +838,8 @@ if(BUILD_TESTING)
${build_generator_args}
--build-project LibName
--build-exe-dir "${CMake_BINARY_DIR}/Tests/LibName/lib"
+ --build-options
+ -DMAKE_SUPPORTS_SPACES=${MAKE_SUPPORTS_SPACES}
--test-command foobar
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LibName")
@@ -1421,6 +1433,7 @@ if(BUILD_TESTING)
CURL
Cups
Doxygen
+ DevIL
EnvModules
EXPAT
Fontconfig
@@ -1475,6 +1488,10 @@ if(BUILD_TESTING)
add_subdirectory(CudaOnly)
endif()
+ if(CMake_TEST_HIP)
+ add_subdirectory(HIP)
+ endif()
+
if(CMake_TEST_ISPC)
add_subdirectory(ISPC)
endif()
@@ -1693,7 +1710,7 @@ if(BUILD_TESTING)
${build_generator_args}
--build-project ${import_name}
--build-options
- "-DCMAKE_PREFIX_PATH:PATH=${install_dir}/lib/cmake")
+ "-DCMAKE_PREFIX_PATH:PATH=${install_dir}")
set_tests_properties(${import_test_name} PROPERTIES DEPENDS ${export_test_name})
list(APPEND TEST_BUILD_DIRS "${import_build_dir}")
endfunction()
@@ -1738,33 +1755,61 @@ if(BUILD_TESTING)
add_test(testdriver1 ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/TestDriver"
- "${CMake_BINARY_DIR}/Tests/TestDriver"
+ "${CMake_BINARY_DIR}/Tests/TestDriver1"
${build_generator_args}
--build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
--build-project TestDriverTest
--test-command TestDriverTest test1
)
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver1")
add_test(testdriver2 ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/TestDriver"
- "${CMake_BINARY_DIR}/Tests/TestDriver"
+ "${CMake_BINARY_DIR}/Tests/TestDriver2"
${build_generator_args}
--build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
--build-project TestDriverTest
--test-command TestDriverTest test2
)
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver2")
add_test(testdriver3 ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/TestDriver"
- "${CMake_BINARY_DIR}/Tests/TestDriver"
+ "${CMake_BINARY_DIR}/Tests/TestDriver3"
${build_generator_args}
--build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
--build-project TestDriverTest
--test-command TestDriverTest subdir/test3
)
- list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver")
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver3")
+
+ add_test(testdriver4 ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/TestDriver"
+ "${CMake_BINARY_DIR}/Tests/TestDriver4"
+ ${build_generator_args}
+ --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
+ --build-project TestDriverTest
+ --test-command TestDriverTest -A test2
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver4")
+
+ add_test(testdriver5 ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/TestDriver"
+ "${CMake_BINARY_DIR}/Tests/TestDriver5"
+ ${build_generator_args}
+ --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
+ --build-project TestDriverTest
+ --test-command TestDriverTest -A test2
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver5")
+ set_tests_properties(testdriver5 PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "TAP version 13\n1\\.\\.3.+ok 1 test1 # [0-9]+\\.[0-9]+.*All tests finished."
+ )
add_test(Dependency ${CMAKE_CTEST_COMMAND}
--build-and-test
@@ -2417,6 +2462,9 @@ if(BUILD_TESTING)
if(vs16 AND CMake_TEST_ANDROID_VS16)
add_test_VSAndroid(vs16 "Visual Studio 16 2019" "ARM")
endif()
+ if(vs17 AND CMake_TEST_ANDROID_VS17)
+ add_test_VSAndroid(vs17 "Visual Studio 17 2022" "ARM")
+ endif()
if (APPLE)
if (CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
diff --git a/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt
index 7ca68ecf4..aca99ceff 100644
--- a/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt
@@ -36,7 +36,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES Intel)
string (REGEX REPLACE ".*Version ([0-9]+(\\.[0-9]+)+).*" "\\1" _intel_version "${_intel_version_info}")
endif()
-message("Platform:\n WIN32: ${WIN32}\n UNIX: ${UNIX}\n APPLE: ${APPLE}\n MINGW: ${MINGW}\n CYGWIN: ${CYGWIN}\n"
+message("Platform:\n WIN32: ${WIN32}\n UNIX: ${UNIX}\n APPLE: ${APPLE}\n MINGW: ${MINGW}\n CYGWIN: ${CYGWIN}\n MSYS: ${MSYS}\n"
" MSVC: ${MSVC}\n MSVC60: ${MSVC60}\n MSVC70: ${MSVC70}\n MSVC71: ${MSVC71}\n MSVC80: ${MSVC80}\n MSVC90: ${MSVC90}\n MSVC10: ${MSVC10}\n"
" GCC: ${_gcc_version}\n"
" Clang: ${_clang_version}\n"
diff --git a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
index 2028a135c..2784e3bc5 100644
--- a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
@@ -9,7 +9,7 @@
project(CheckCXXSymbolExists CXX)
-cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
+cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
set(CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/../CheckSymbolExists")
diff --git a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
index 1570c3789..2e5d8d3b2 100644
--- a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.8)
+cmake_minimum_required (VERSION 2.8.12)
project(CheckLanguage NONE)
include(CheckLanguage)
diff --git a/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt
index 7f01463c0..9a9bb2a39 100644
--- a/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt
@@ -9,7 +9,7 @@
project(CheckSymbolExists C)
-cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
+cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
set(CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}")
diff --git a/Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt b/Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt
index 56e449afd..d66eb06d7 100644
--- a/Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt
+++ b/Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.8)
+cmake_minimum_required (VERSION 2.8.12)
project(LinkInterfaceLoop C)
# Add a shared library that incorrectly names itself as a
diff --git a/Tests/CMakeOnly/TargetScope/CMakeLists.txt b/Tests/CMakeOnly/TargetScope/CMakeLists.txt
index fa5d8e234..faf225099 100644
--- a/Tests/CMakeOnly/TargetScope/CMakeLists.txt
+++ b/Tests/CMakeOnly/TargetScope/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.8)
+cmake_minimum_required (VERSION 2.8.12)
project(TargetScope NONE)
add_subdirectory(Sub)
diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt
index 6bbbe7d35..52959e62e 100644
--- a/Tests/CMakeTests/CMakeLists.txt
+++ b/Tests/CMakeTests/CMakeLists.txt
@@ -7,6 +7,7 @@ macro(AddCMakeTest TestName PreArgs)
add_test(NAME CMake.${TestName}
COMMAND ${CMAKE_EXECUTABLE} ${PreArgs}
-P "${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" ${ARGN})
+ set_tests_properties("CMake.${TestName}" PROPERTIES LABELS "CMake;command")
endmacro()
diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
index f01e616f0..63c234acf 100644
--- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
+++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
@@ -2,6 +2,9 @@
# test it.
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
+set(CMAKE_FIND_LIBRARY_PREFIXES "disabled-for-test-")
+set(CMAKE_FIND_LIBRARY_SUFFIXES "-disabled-for-test")
+
#-----------------------------------------------------------------------------
# Linux
@@ -459,7 +462,28 @@ set(msys_g77_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/so
list(APPEND platforms msys_g77)
#-----------------------------------------------------------------------------
-# MSYS2
+# MSYS2-runtime
+
+# gcc dummy.c -v
+set(msys2rt_gcc_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/cczg1Arh.o -lgcc -lmsys-2.0 -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc")
+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)
+
+# 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++)
+
+# 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)
+
+#-----------------------------------------------------------------------------
+# MSYS2-mingw
# gcc dummy.c -v
set(msys2_gcc_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/ccikz9Wf.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -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 -plugin-opt=-pass-through=-lgcc_eh -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/ccK0dTUv.o -lmingw32 -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc -lgcc_eh -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")
diff --git a/Tests/CPackComponents/CMakeLists.txt b/Tests/CPackComponents/CMakeLists.txt
index 5b03c9e42..c1b348ef4 100644
--- a/Tests/CPackComponents/CMakeLists.txt
+++ b/Tests/CPackComponents/CMakeLists.txt
@@ -4,7 +4,7 @@
# application (mylibapp). We create a binary installer that allows
# users to select which pieces will be installed: the example
# application, the library binaries, and/or the header file.
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.8.12)
project(CPackComponents)
# Create the mylib library
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
index 8f7c19810..b61e62dfc 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
@@ -146,7 +146,7 @@ endfunction()
# This function runs dpkg-deb on a .deb and returns its output
-# the default behaviour it to run "--info" on the specified Debian package
+# the default behavior it to run "--info" on the specified Debian package
# ACTION is one of the option accepted by dpkg-deb
function(run_dpkgdeb dpkg_deb_output)
set(${dpkg_deb_output} "" PARENT_SCOPE)
diff --git a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in
index a6f6ea9e8..1105cb83f 100644
--- a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in
+++ b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in
@@ -20,7 +20,7 @@ if(CPACK_GENERATOR MATCHES "RPM")
set(CPACK_RPM_HEADERS_PACKAGE_ARCHITECTURE "noarch")
# test cross-built rpm
- set(CPACK_RPM_APPLICATIONS_PACKAGE_ARCHITECTURE "armv7hf")
+ set(CPACK_RPM_APPLICATIONS_PACKAGE_ARCHITECTURE "armv7hl")
# test package summary override - headers rpm is generated in the middle
set(CPACK_RPM_PACKAGE_SUMMARY "default summary")
diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
index f3d3ad03f..260a0f82a 100644
--- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
+++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
@@ -115,8 +115,17 @@ execute_process(COMMAND ${CMAKE_CPACK_COMMAND} ${config_verbose} -G ${CPackGen}
ERROR_VARIABLE CPack_error
WORKING_DIRECTORY ${CPackComponentsForAll_BINARY_DIR})
+string(REPLACE "\n" "\n cpack-out> " cpack_out "\n${CPack_output}")
+string(REPLACE "\n" "\n cpack-err> " cpack_err "\n${CPack_error}")
+string(REPLACE "\n" "\n cpack-res> " cpack_res "\n${CPack_result}")
+string(CONCAT output_error_message
+ "CPack output:${cpack_out}\n"
+ "CPack error:${cpack_err}\n"
+ "CPack result:${cpack_res}\n"
+ )
+
if(CPack_result)
- message(FATAL_ERROR "error: CPack execution went wrong!, CPack_output=${CPack_output}, CPack_error=${CPack_error}")
+ message(FATAL_ERROR "error: CPack execution went wrong!,\n${output_error_message}")
else ()
message(STATUS "CPack_output=${CPack_output}")
endif()
@@ -132,13 +141,13 @@ if(expected_file_mask)
message(STATUS "expected_file_mask='${expected_file_mask}'")
if(NOT expected_file)
- message(FATAL_ERROR "error: expected_file does not exist: CPackComponentsForAll test fails. (CPack_output=${CPack_output}, CPack_error=${CPack_error}")
+ message(FATAL_ERROR "error: expected_file does not exist: CPackComponentsForAll test fails.\n${output_error_message}")
endif()
list(LENGTH expected_file actual_count)
message(STATUS "actual_count='${actual_count}'")
if(NOT actual_count EQUAL expected_count)
- message(FATAL_ERROR "error: expected_count=${expected_count} does not match actual_count=${actual_count}: CPackComponents test fails. (CPack_output=${CPack_output}, CPack_error=${CPack_error})")
+ message(FATAL_ERROR "error: expected_count=${expected_count} does not match actual_count=${actual_count}: CPackComponents test fails.\n${output_error_message}")
endif()
if(expect_dmg_sla)
@@ -261,7 +270,7 @@ if(CPackGen MATCHES "RPM")
set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*")
set(check_file_match_expected_description ".*${CPACK_COMPONENT_APPLICATIONS_DESCRIPTION}.*")
set(check_file_match_expected_relocation_path "Relocations${whitespaces}:${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
- set(check_file_match_expected_architecture "armv7hf")
+ set(check_file_match_expected_architecture "armv7hl")
set(spec_regex "*applications*")
set(check_content_list "^/usr/foo/bar
/usr/foo/bar/bin
@@ -404,7 +413,7 @@ if(CPackGen MATCHES "RPM")
elseif("${symlink_name}" STREQUAL "symlink_other_relocatable_path"
OR "${symlink_name}" STREQUAL "symlink_from_non_relocatable_path"
OR "${symlink_name}" STREQUAL "symlink_relocatable_subpath")
- # these links were not canged - post install script only - ignore them
+ # these links were not changed - post install script only - ignore them
else()
message(FATAL_ERROR "error: unexpected rpm symbolic link '${check_symlink}'")
endif()
diff --git a/Tests/CSharpOnly/CMakeLists.txt b/Tests/CSharpOnly/CMakeLists.txt
index 195af05cb..f7928b675 100644
--- a/Tests/CSharpOnly/CMakeLists.txt
+++ b/Tests/CSharpOnly/CMakeLists.txt
@@ -9,8 +9,13 @@ source_group(nested FILES nested/lib1.cs)
add_library(lib2 SHARED lib2.cs)
add_executable(CSharpOnly csharponly.cs)
-
target_link_libraries(CSharpOnly lib1 lib2)
+add_executable(CSharpConfigSpecific
+ $<$<CONFIG:Debug>:config_specific_main_debug.cs>
+ $<$<NOT:$<CONFIG:Debug>>:config_specific_main_not_debug.cs>
+ $<$<CONFIG:NotAConfig>:config_specific_main_no_exist.cs>
+ )
+
add_custom_target(CSharpCustom ALL SOURCES empty.cs)
add_custom_target(custom.cs ALL DEPENDS empty.txt)
diff --git a/Tests/CSharpOnly/config_specific_main_debug.cs b/Tests/CSharpOnly/config_specific_main_debug.cs
new file mode 100644
index 000000000..b62524b74
--- /dev/null
+++ b/Tests/CSharpOnly/config_specific_main_debug.cs
@@ -0,0 +1,10 @@
+namespace CSharpConfigSpecific
+{
+ class CSharpConfigSpecific
+ {
+ public static void Main(string[] args)
+ {
+ return;
+ }
+ }
+}
diff --git a/Tests/CSharpOnly/config_specific_main_no_exist.cs b/Tests/CSharpOnly/config_specific_main_no_exist.cs
new file mode 100644
index 000000000..b62524b74
--- /dev/null
+++ b/Tests/CSharpOnly/config_specific_main_no_exist.cs
@@ -0,0 +1,10 @@
+namespace CSharpConfigSpecific
+{
+ class CSharpConfigSpecific
+ {
+ public static void Main(string[] args)
+ {
+ return;
+ }
+ }
+}
diff --git a/Tests/CSharpOnly/config_specific_main_not_debug.cs b/Tests/CSharpOnly/config_specific_main_not_debug.cs
new file mode 100644
index 000000000..b62524b74
--- /dev/null
+++ b/Tests/CSharpOnly/config_specific_main_not_debug.cs
@@ -0,0 +1,10 @@
+namespace CSharpConfigSpecific
+{
+ class CSharpConfigSpecific
+ {
+ public static void Main(string[] args)
+ {
+ return;
+ }
+ }
+}
diff --git a/Tests/CTestTest2/test.cmake.in b/Tests/CTestTest2/test.cmake.in
index a9bbc527d..d5d4d2f39 100644
--- a/Tests/CTestTest2/test.cmake.in
+++ b/Tests/CTestTest2/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestBadExe/test.cmake.in b/Tests/CTestTestBadExe/test.cmake.in
index 43a85725b..dd180f0fe 100644
--- a/Tests/CTestTestBadExe/test.cmake.in
+++ b/Tests/CTestTestBadExe/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestChecksum/test.cmake.in b/Tests/CTestTestChecksum/test.cmake.in
index 2a435d208..3bac0e00b 100644
--- a/Tests/CTestTestChecksum/test.cmake.in
+++ b/Tests/CTestTestChecksum/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestCostSerial/test.cmake.in b/Tests/CTestTestCostSerial/test.cmake.in
index 9b32a468b..1c46d4ca5 100644
--- a/Tests/CTestTestCostSerial/test.cmake.in
+++ b/Tests/CTestTestCostSerial/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestCrash/CMakeLists.txt b/Tests/CTestTestCrash/CMakeLists.txt
index 77986df34..663d2e45c 100644
--- a/Tests/CTestTestCrash/CMakeLists.txt
+++ b/Tests/CTestTestCrash/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestCrash)
include(CTest)
diff --git a/Tests/CTestTestCrash/test.cmake.in b/Tests/CTestTestCrash/test.cmake.in
index 3641cb01f..916d4e9fc 100644
--- a/Tests/CTestTestCrash/test.cmake.in
+++ b/Tests/CTestTestCrash/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestCycle/CMakeLists.txt b/Tests/CTestTestCycle/CMakeLists.txt
index 6ba6b8c95..19f4dd7d1 100644
--- a/Tests/CTestTestCycle/CMakeLists.txt
+++ b/Tests/CTestTestCycle/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestCycle)
include(CTest)
diff --git a/Tests/CTestTestCycle/test.cmake.in b/Tests/CTestTestCycle/test.cmake.in
index 4a63dd612..507d46bc5 100644
--- a/Tests/CTestTestCycle/test.cmake.in
+++ b/Tests/CTestTestCycle/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestDepends/CMakeLists.txt b/Tests/CTestTestDepends/CMakeLists.txt
index 5cd6d6665..462ad8c7a 100644
--- a/Tests/CTestTestDepends/CMakeLists.txt
+++ b/Tests/CTestTestDepends/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestDepends)
include(CTest)
diff --git a/Tests/CTestTestDepends/test.cmake.in b/Tests/CTestTestDepends/test.cmake.in
index 74fddb3d3..11bc92a25 100644
--- a/Tests/CTestTestDepends/test.cmake.in
+++ b/Tests/CTestTestDepends/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestFailure/CMakeLists.txt b/Tests/CTestTestFailure/CMakeLists.txt
index 01fbb2c4f..db14b3d92 100644
--- a/Tests/CTestTestFailure/CMakeLists.txt
+++ b/Tests/CTestTestFailure/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestFailure)
include(CTest)
diff --git a/Tests/CTestTestFailure/testNoBuild.cmake.in b/Tests/CTestTestFailure/testNoBuild.cmake.in
index 86333af4a..47d254f56 100644
--- a/Tests/CTestTestFailure/testNoBuild.cmake.in
+++ b/Tests/CTestTestFailure/testNoBuild.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestFailure/testNoExe.cmake.in b/Tests/CTestTestFailure/testNoExe.cmake.in
index 8875cee36..8496c80e1 100644
--- a/Tests/CTestTestFailure/testNoExe.cmake.in
+++ b/Tests/CTestTestFailure/testNoExe.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestLabelRegExp/test.cmake.in b/Tests/CTestTestLabelRegExp/test.cmake.in
index 5c0c9d7ff..dd40c3b50 100644
--- a/Tests/CTestTestLabelRegExp/test.cmake.in
+++ b/Tests/CTestTestLabelRegExp/test.cmake.in
@@ -27,11 +27,15 @@ expect_test_list("test1.*test3.*Total Tests: 2" --label-regex foo)
expect_test_list("test2.*test3.*Total Tests: 2" --label-regex bar)
expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-regex foo|bar)
expect_test_list("Total Tests: 0" --label-regex baz)
+expect_test_list("Total Tests: 0" --label-regex foo --label-regex baz)
+expect_test_list("test3.*Total Tests: 1" --label-regex foo --label-regex bar)
expect_test_list("test2.*Total Tests: 1" --label-exclude foo)
expect_test_list("test1.*Total Tests: 1" --label-exclude bar)
expect_test_list("Total Tests: 0" --label-exclude foo|bar)
expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-exclude baz)
+expect_test_list("test1.*test2.*Total Tests: 2" --label-exclude foo --label-exclude bar)
+expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-exclude foo --label-exclude baz)
expect_test_list("test1.*Total Tests: 1" --label-regex foo --label-exclude bar)
expect_test_list("test2.*Total Tests: 1" --label-regex bar --label-exclude foo)
diff --git a/Tests/CTestTestParallel/CMakeLists.txt b/Tests/CTestTestParallel/CMakeLists.txt
index e47085a09..819fee4eb 100644
--- a/Tests/CTestTestParallel/CMakeLists.txt
+++ b/Tests/CTestTestParallel/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestParallel)
include(CTest)
diff --git a/Tests/CTestTestParallel/test.cmake.in b/Tests/CTestTestParallel/test.cmake.in
index 045a4ca06..517db726e 100644
--- a/Tests/CTestTestParallel/test.cmake.in
+++ b/Tests/CTestTestParallel/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestResourceLock/CMakeLists.txt b/Tests/CTestTestResourceLock/CMakeLists.txt
index 4001643fd..4bc4366c3 100644
--- a/Tests/CTestTestResourceLock/CMakeLists.txt
+++ b/Tests/CTestTestResourceLock/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestResourceLock)
include(CTest)
diff --git a/Tests/CTestTestResourceLock/test.cmake.in b/Tests/CTestTestResourceLock/test.cmake.in
index 67dde1803..826226de0 100644
--- a/Tests/CTestTestResourceLock/test.cmake.in
+++ b/Tests/CTestTestResourceLock/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestScheduler/CMakeLists.txt b/Tests/CTestTestScheduler/CMakeLists.txt
index ccd7b2cbb..a3f0f27cd 100644
--- a/Tests/CTestTestScheduler/CMakeLists.txt
+++ b/Tests/CTestTestScheduler/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project (CTestTestScheduler)
include (CTest)
diff --git a/Tests/CTestTestScheduler/test.cmake.in b/Tests/CTestTestScheduler/test.cmake.in
index f8c8ab747..5dcfb635a 100644
--- a/Tests/CTestTestScheduler/test.cmake.in
+++ b/Tests/CTestTestScheduler/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestSkipReturnCode/test.cmake.in b/Tests/CTestTestSkipReturnCode/test.cmake.in
index 112b0cd0f..2988d2fe9 100644
--- a/Tests/CTestTestSkipReturnCode/test.cmake.in
+++ b/Tests/CTestTestSkipReturnCode/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestStopTime/CMakeLists.txt b/Tests/CTestTestStopTime/CMakeLists.txt
index bd8bebdda..08116e25b 100644
--- a/Tests/CTestTestStopTime/CMakeLists.txt
+++ b/Tests/CTestTestStopTime/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestStopTime)
include(CTest)
diff --git a/Tests/CTestTestStopTime/test.cmake.in b/Tests/CTestTestStopTime/test.cmake.in
index d3a9a4a92..3797d40ed 100644
--- a/Tests/CTestTestStopTime/test.cmake.in
+++ b/Tests/CTestTestStopTime/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestSubdir/CMakeLists.txt b/Tests/CTestTestSubdir/CMakeLists.txt
index b7cc7e2f1..87c4604d8 100644
--- a/Tests/CTestTestSubdir/CMakeLists.txt
+++ b/Tests/CTestTestSubdir/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestSubdir)
include(CTest)
diff --git a/Tests/CTestTestSubdir/test.cmake.in b/Tests/CTestTestSubdir/test.cmake.in
index 8b3957b4e..3b1fb5fc8 100644
--- a/Tests/CTestTestSubdir/test.cmake.in
+++ b/Tests/CTestTestSubdir/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestTimeout/test.cmake.in b/Tests/CTestTestTimeout/test.cmake.in
index 4b5157ef0..ce9c4979f 100644
--- a/Tests/CTestTestTimeout/test.cmake.in
+++ b/Tests/CTestTestTimeout/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestUpload/CMakeLists.txt b/Tests/CTestTestUpload/CMakeLists.txt
index 90d811cd9..5e02b2f4a 100644
--- a/Tests/CTestTestUpload/CMakeLists.txt
+++ b/Tests/CTestTestUpload/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestUpload)
add_executable (Sleep sleep.c)
diff --git a/Tests/CTestTestUpload/test.cmake.in b/Tests/CTestTestUpload/test.cmake.in
index 701439d37..74fd1ecdf 100644
--- a/Tests/CTestTestUpload/test.cmake.in
+++ b/Tests/CTestTestUpload/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestVerboseOutput/CMakeLists.txt b/Tests/CTestTestVerboseOutput/CMakeLists.txt
index 4cdd29c68..379238584 100644
--- a/Tests/CTestTestVerboseOutput/CMakeLists.txt
+++ b/Tests/CTestTestVerboseOutput/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CTestTestVerboseOutput)
include(CTest)
diff --git a/Tests/CTestTestVerboseOutput/test.cmake.in b/Tests/CTestTestVerboseOutput/test.cmake.in
index 7f4954841..9c9a4dca8 100644
--- a/Tests/CTestTestVerboseOutput/test.cmake.in
+++ b/Tests/CTestTestVerboseOutput/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CTestTestZeroTimeout/CMakeLists.txt b/Tests/CTestTestZeroTimeout/CMakeLists.txt
index 4d2b79dc2..2d404c8cb 100644
--- a/Tests/CTestTestZeroTimeout/CMakeLists.txt
+++ b/Tests/CTestTestZeroTimeout/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project (CTestTestZeroTimeout)
include (CTest)
diff --git a/Tests/CTestTestZeroTimeout/test.cmake.in b/Tests/CTestTestZeroTimeout/test.cmake.in
index b829fefe2..50dbba03f 100644
--- a/Tests/CTestTestZeroTimeout/test.cmake.in
+++ b/Tests/CTestTestZeroTimeout/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.4)
+cmake_minimum_required(VERSION 2.8.12)
# Settings:
set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
diff --git a/Tests/CheckFortran.cmake b/Tests/CheckFortran.cmake
index 33e1bfbbb..36293f51c 100644
--- a/Tests/CheckFortran.cmake
+++ b/Tests/CheckFortran.cmake
@@ -7,7 +7,7 @@ if(NOT DEFINED CMAKE_Fortran_COMPILER)
message(STATUS ${_desc})
file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckFortran)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckFortran/CMakeLists.txt"
- "cmake_minimum_required(VERSION 2.4)
+ "cmake_minimum_required(VERSION 2.8.12)
project(CheckFortran Fortran)
file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
\"set(CMAKE_Fortran_COMPILER \\\"\${CMAKE_Fortran_COMPILER}\\\")\\n\"
diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt
index cff98e3c5..20988ac46 100644
--- a/Tests/CompileFeatures/CMakeLists.txt
+++ b/Tests/CompileFeatures/CMakeLists.txt
@@ -18,7 +18,7 @@ macro(run_test feature lang)
endif()
endmacro()
-if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$")
+if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu|FujitsuClang)$")
get_property(c_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES)
list(FILTER c_features EXCLUDE REGEX "^c_std_[0-9][0-9]")
foreach(feature ${c_features})
@@ -26,7 +26,7 @@ if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$")
endforeach()
endif()
-if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$")
+if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu|FujitsuClang)$")
get_property(cxx_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
list(FILTER cxx_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]")
foreach(feature ${cxx_features})
@@ -237,6 +237,8 @@ if (C_expected_features)
if (std_flag_idx EQUAL -1)
add_executable(default_dialect_C default_dialect.c)
target_compile_definitions(default_dialect_C PRIVATE
+ DEFAULT_C23=$<EQUAL:${CMAKE_C_STANDARD_DEFAULT},23>
+ DEFAULT_C17=$<EQUAL:${CMAKE_C_STANDARD_DEFAULT},17>
DEFAULT_C11=$<EQUAL:${CMAKE_C_STANDARD_DEFAULT},11>
DEFAULT_C99=$<EQUAL:${CMAKE_C_STANDARD_DEFAULT},99>
DEFAULT_C90=$<EQUAL:${CMAKE_C_STANDARD_DEFAULT},90>
diff --git a/Tests/CompileFeatures/cxx_contextual_conversions.cpp b/Tests/CompileFeatures/cxx_contextual_conversions.cpp
index 247f13f9f..fe8d5c0f5 100644
--- a/Tests/CompileFeatures/cxx_contextual_conversions.cpp
+++ b/Tests/CompileFeatures/cxx_contextual_conversions.cpp
@@ -1,4 +1,3 @@
-
#define assert(E) \
if (!(E)) \
return 1;
@@ -38,6 +37,7 @@ int someFunc()
}
int* vp = new int[i];
+ delete[] vp;
return 0;
}
diff --git a/Tests/CompileFeatures/default_dialect.c b/Tests/CompileFeatures/default_dialect.c
index 6160c2f44..b990e5325 100644
--- a/Tests/CompileFeatures/default_dialect.c
+++ b/Tests/CompileFeatures/default_dialect.c
@@ -1,5 +1,13 @@
-#if DEFAULT_C11
+#if DEFAULT_C23
+# if __STDC_VERSION__ <= 201710L
+# error Unexpected value for __STDC_VERSION__.
+# endif
+#elif DEFAULT_C17
+# if __STDC_VERSION__ < 201710L
+# error Unexpected value for __STDC_VERSION__.
+# endif
+#elif DEFAULT_C11
# if __STDC_VERSION__ < 201112L
# error Unexpected value for __STDC_VERSION__.
# endif
diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt
index cd6cacd75..96bafeadd 100644
--- a/Tests/CompileOptions/CMakeLists.txt
+++ b/Tests/CompileOptions/CMakeLists.txt
@@ -1,5 +1,11 @@
-cmake_minimum_required(VERSION 2.8.12)
-
+cmake_minimum_required(VERSION 3.0)
+if(POLICY CMP0092)
+ cmake_policy(SET CMP0092 NEW)
+endif()
+get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(NOT _isMultiConfig AND NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE)
+endif()
project(CompileOptions)
add_library(testlib other.cpp)
@@ -49,6 +55,24 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Borland|Embarcadero" AND NOT "${CMAK
)
endif()
+if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|AppleClang|MSVC)$")
+ target_compile_definitions(CompileOptions PRIVATE "DO_FLAG_TESTS")
+ if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|AppleClang)$")
+ string(APPEND CMAKE_CXX_FLAGS " -w")
+ endif()
+ string(APPEND CMAKE_CXX_FLAGS " -DFLAG_A=1 -DFLAG_B=1")
+ string(APPEND CMAKE_CXX_FLAGS_DEBUG " -DFLAG_A=2 -DFLAG_C=1")
+ string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DFLAG_A=2 -DFLAG_C=1")
+ string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DFLAG_A=2 -DFLAG_C=1")
+ string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DFLAG_A=2 -DFLAG_C=1")
+ set_property(TARGET CompileOptions APPEND PROPERTY COMPILE_OPTIONS "-DFLAG_B=2" "-DFLAG_C=2" "-DFLAG_D=1")
+ set_property(TARGET testlib APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "-DFLAG_D=2")
+ if(NOT CMAKE_GENERATOR MATCHES "^Visual Studio 9")
+ set_property(TARGET testlib APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "-DFLAG_E=1")
+ set_property(SOURCE main.cpp PROPERTY COMPILE_OPTIONS "-DFLAG_E=2")
+ endif()
+endif()
+
target_link_libraries(CompileOptions testlib)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
diff --git a/Tests/CompileOptions/main.cpp b/Tests/CompileOptions/main.cpp
index ebc101762..23ce1970f 100644
--- a/Tests/CompileOptions/main.cpp
+++ b/Tests/CompileOptions/main.cpp
@@ -37,6 +37,24 @@
# endif
#endif
+#ifdef DO_FLAG_TESTS
+# if FLAG_A != 2
+# error "FLAG_A is not 2"
+# endif
+# if FLAG_B != 2
+# error "FLAG_B is not 2"
+# endif
+# if FLAG_C != 2
+# error "FLAG_C is not 2"
+# endif
+# if FLAG_D != 2
+# error "FLAG_D is not 2"
+# endif
+# if defined(FLAG_E) && FLAG_E != 2
+# error "FLAG_E is not 2"
+# endif
+#endif
+
#include <string.h>
int main()
diff --git a/Tests/ConfigSources/CMakeLists.txt b/Tests/ConfigSources/CMakeLists.txt
index a3d98f685..38475f86d 100644
--- a/Tests/ConfigSources/CMakeLists.txt
+++ b/Tests/ConfigSources/CMakeLists.txt
@@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.0)
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+
if(NOT _isMultiConfig AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE)
endif()
@@ -74,10 +75,10 @@ add_custom_command(APPEND
VERBATIM
)
foreach(n RANGE 1 5)
- set_property(SOURCE custom${n}_Debug.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_DEBUG)
- foreach(other Release RelWithDebInfo MinSizeRel)
+ foreach(other ${CMAKE_BUILD_TYPE} Release RelWithDebInfo MinSizeRel)
set_property(SOURCE custom${n}_${other}.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_OTHER)
endforeach()
+ set_property(SOURCE custom${n}_Debug.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_DEBUG)
endforeach()
add_library(Custom STATIC
custom1_$<CONFIG>.cpp
diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt
index 80545c483..fa06a94fa 100644
--- a/Tests/CustomCommand/CMakeLists.txt
+++ b/Tests/CustomCommand/CMakeLists.txt
@@ -1,7 +1,7 @@
#
# Wrapping
#
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project (CustomCommand)
add_subdirectory(GeneratedHeader)
@@ -583,6 +583,6 @@ set_target_properties(mac_fw PROPERTIES
add_custom_command(OUTPUT mac_fw.txt COMMAND ${CMAKE_COMMAND} -E touch mac_fw.txt DEPENDS mac_fw)
add_custom_target(drive_mac_fw ALL DEPENDS mac_fw.txt)
-# Test empty COMMANDs are ommited
+# Test empty COMMANDs are omitted
add_executable(empty_command empty_command.cxx)
add_custom_command(TARGET empty_command POST_BUILD COMMAND $<0:date>)
diff --git a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt
index 3bab1fec0..7697a9b72 100644
--- a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt
+++ b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(TestWorkingDir)
add_custom_command(
diff --git a/Tests/Dependency/CMakeLists.txt b/Tests/Dependency/CMakeLists.txt
index ebc2d1066..58d3fb7c5 100644
--- a/Tests/Dependency/CMakeLists.txt
+++ b/Tests/Dependency/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project( Dependency )
# to test directories with only one character One was changed to 1
diff --git a/Tests/ExportImport/CMakeLists.txt b/Tests/ExportImport/CMakeLists.txt
index d88eb11bb..e3f32c2cf 100644
--- a/Tests/ExportImport/CMakeLists.txt
+++ b/Tests/ExportImport/CMakeLists.txt
@@ -16,14 +16,12 @@ set_property(
)
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
-if(_isMultiConfig)
- set(NESTED_CONFIG_TYPE -C "${CMAKE_CFG_INTDIR}")
+if(_isMultiConfig OR CMAKE_BUILD_TYPE)
+ set(NESTED_CONFIG_TYPE -C "$<CONFIG>")
+ set(NESTED_CONFIG_INSTALL_TYPE --config "$<CONFIG>")
else()
- if(CMAKE_BUILD_TYPE)
- set(NESTED_CONFIG_TYPE -C "${CMAKE_BUILD_TYPE}")
- else()
- set(NESTED_CONFIG_TYPE)
- endif()
+ set(NESTED_CONFIG_TYPE)
+ set(NESTED_CONFIG_INSTALL_TYPE)
endif()
if(MINGW OR MSYS)
@@ -79,5 +77,29 @@ set_property(
PROPERTY SYMBOLIC 1
)
+# Run the install tests.
+set(install_deps)
+set(rdep_tests)
+if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Windows|Darwin)$" AND NOT CMake_INSTALL_NAME_TOOL_BUG)
+ set(rdep_tests RUNTIME_DEPENDENCIES RUNTIME_DEPENDENCY_SET)
+endif()
+foreach(name IMPORTED_RUNTIME_ARTIFACTS ${rdep_tests})
+ add_custom_command(
+ OUTPUT ${ExportImport_BINARY_DIR}/ImportInstall-${name}
+ COMMAND ${CMAKE_COMMAND} -E rm -rf ${ExportImport_BINARY_DIR}/Import/install-${name}/install
+ COMMAND ${CMAKE_COMMAND}
+ --install ${ExportImport_BINARY_DIR}/Import/install-${name}
+ --prefix ${ExportImport_BINARY_DIR}/Import/install-${name}/install
+ ${NESTED_CONFIG_INSTALL_TYPE}
+ )
+ list(APPEND install_deps ${ExportImport_BINARY_DIR}/ImportInstall-${name})
+ set_property(
+ SOURCE ${ExportImport_BINARY_DIR}/ImportInstall-${name}
+ PROPERTY SYMBOLIC 1
+ )
+endforeach()
+add_custom_target(ImportInstallTarget ALL DEPENDS ${install_deps})
+add_dependencies(ImportInstallTarget ImportTarget)
+
add_executable(ExportImport main.c)
add_dependencies(ExportImport ImportTarget)
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index 6d9b4ab4f..a2968d433 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -395,6 +395,10 @@ target_include_directories(systemlib
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)
+add_library(testMod1 MODULE empty.cpp)
+add_library(testMod2 MODULE empty.cpp)
+set_property(TARGET testMod2 PROPERTY BUNDLE 1)
+
install(TARGETS testLibRequired
EXPORT RequiredExp DESTINATION lib
INCLUDES DESTINATION
@@ -523,6 +527,7 @@ install(
testLibDeprecation
testLibCycleA testLibCycleB
testLibNoSONAME
+ testMod1 testMod2
cmp0022NEW cmp0022OLD
TopDirLib SubDirLinkA
systemlib
@@ -595,6 +600,7 @@ export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 te
testLib4lib testLib4libdbg testLib4libopt
testLibCycleA testLibCycleB
testLibNoSONAME
+ testMod1 testMod2
testLibPerConfigDest
NAMESPACE bld_
APPEND FILE ExportBuildTree.cmake
@@ -684,3 +690,5 @@ if(NOT XCODE)
install(TARGETS testLibFromGeneratedSource EXPORT testLibFromGeneratedSource_Export)
install(EXPORT testLibFromGeneratedSource_Export DESTINATION lib)
endif()
+
+add_subdirectory(install-RUNTIME_DEPENDENCY_SET)
diff --git a/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt b/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt
new file mode 100644
index 000000000..f50cc1d40
--- /dev/null
+++ b/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt
@@ -0,0 +1,42 @@
+cmake_minimum_required(VERSION 3.20)
+
+set(CMAKE_SKIP_RPATH OFF)
+
+foreach(i 1 2 3 4 5 6 7 8 9 10 11 12)
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dep${i}.c"
+"#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void dep${i}(void)
+{
+}
+")
+ add_library(dep${i} SHARED "${CMAKE_CURRENT_BINARY_DIR}/dep${i}.c")
+endforeach()
+
+set_target_properties(dep9 PROPERTIES
+ FRAMEWORK TRUE
+ )
+set_target_properties(dep2 PROPERTIES
+ VERSION 1.2.3
+ SOVERSION 1
+ )
+
+add_library(deplib SHARED deplib.c)
+target_link_libraries(deplib PRIVATE dep1)
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set_target_properties(deplib PROPERTIES
+ INSTALL_RPATH "@loader_path/"
+ )
+endif()
+
+install(TARGETS dep1 dep2 dep3 dep4 dep5 dep6 dep7 dep8 dep9 dep10 dep11 dep12 deplib EXPORT install-RUNTIME_DEPENDENCY_SET
+ RUNTIME DESTINATION install-RUNTIME_DEPENDENCY_SET/bin
+ LIBRARY DESTINATION install-RUNTIME_DEPENDENCY_SET/lib
+ ARCHIVE DESTINATION install-RUNTIME_DEPENDENCY_SET/lib
+ FRAMEWORK DESTINATION install-RUNTIME_DEPENDENCY_SET/frameworks
+ )
+install(EXPORT install-RUNTIME_DEPENDENCY_SET
+ FILE targets.cmake
+ DESTINATION install-RUNTIME_DEPENDENCY_SET
+ )
diff --git a/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/deplib.c b/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/deplib.c
new file mode 100644
index 000000000..e5da19609
--- /dev/null
+++ b/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/deplib.c
@@ -0,0 +1,12 @@
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ extern void dep1(void);
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void deplib(void)
+{
+ dep1();
+}
diff --git a/Tests/ExportImport/Import/CMakeLists.txt b/Tests/ExportImport/Import/CMakeLists.txt
index a8a98fcb6..006313091 100644
--- a/Tests/ExportImport/Import/CMakeLists.txt
+++ b/Tests/ExportImport/Import/CMakeLists.txt
@@ -26,3 +26,12 @@ add_subdirectory(Interface)
# Test package version range
add_subdirectory(version_range)
+
+# Test install(IMPORTED_RUNTIME_ARTIFACTS)
+add_subdirectory(install-IMPORTED_RUNTIME_ARTIFACTS)
+
+# Test install(RUNTIME_DEPENDENCIES) and install(RUNTIME_DEPENDENCY_SET)
+if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Windows|Darwin)$")
+ add_subdirectory(install-RUNTIME_DEPENDENCIES)
+ add_subdirectory(install-RUNTIME_DEPENDENCY_SET)
+endif()
diff --git a/Tests/ExportImport/Import/Interface/pch_iface_test.cpp b/Tests/ExportImport/Import/Interface/pch_iface_test.cpp
index a18bbde23..d676a5bed 100644
--- a/Tests/ExportImport/Import/Interface/pch_iface_test.cpp
+++ b/Tests/ExportImport/Import/Interface/pch_iface_test.cpp
@@ -3,7 +3,8 @@
# ifndef PCH_PCH_H_INCLUDED
# error "Expected PCH_PCH_H_INCLUDED."
# endif
-#elif defined(__PGIC__) || defined(__ibmxl__) || defined(_CRAYC)
+#elif defined(__PGIC__) || defined(__ibmxl__) || defined(_CRAYC) || \
+ defined(__FUJITSU)
// No PCH expected but these compilers define macros below.
#elif defined(__GNUC__) || defined(__clang__) || defined(_INTEL_COMPILER) || \
defined(_MSC_VER)
diff --git a/Tests/ExportImport/Import/check_installed.cmake b/Tests/ExportImport/Import/check_installed.cmake
new file mode 100644
index 000000000..6e51f9275
--- /dev/null
+++ b/Tests/ExportImport/Import/check_installed.cmake
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.20)
+
+function(check_installed expect)
+ file(GLOB_RECURSE actual
+ LIST_DIRECTORIES TRUE
+ RELATIVE ${CMAKE_INSTALL_PREFIX}
+ ${CMAKE_INSTALL_PREFIX}/*
+ )
+ if(actual)
+ list(SORT actual)
+ endif()
+ if(NOT "${actual}" MATCHES "${expect}")
+ message(FATAL_ERROR "Installed files:
+ ${actual}
+do not match what we expected:
+ ${expect}
+in directory:
+ ${CMAKE_INSTALL_PREFIX}")
+ endif()
+endfunction()
diff --git a/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/CMakeLists.txt b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/CMakeLists.txt
new file mode 100644
index 000000000..76efe2f50
--- /dev/null
+++ b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Import targets from the exported build tree.
+include(${Import_BINARY_DIR}/../Export/ExportBuildTree.cmake)
+
+set(_tgts
+ bld_testExe1 # Ordinary executable
+ bld_testExe2lib # Ordinary shared library
+ bld_testLib3 # Shared library with version and soversion
+ bld_testLib4 # Framework library
+ bld_testExe3 # Bundle executable
+ bld_testMod1 # Module library
+ bld_testMod2 # CFBundle
+ )
+
+install(IMPORTED_RUNTIME_ARTIFACTS ${_tgts}
+ RUNTIME DESTINATION aaa/executables
+ LIBRARY DESTINATION aaa/libraries
+ BUNDLE DESTINATION aaa/bundles
+ FRAMEWORK DESTINATION aaa/frameworks
+ )
+
+install(IMPORTED_RUNTIME_ARTIFACTS ${_tgts}
+ DESTINATION bbb
+ )
+
+install(IMPORTED_RUNTIME_ARTIFACTS ${_tgts}
+ BUNDLE DESTINATION zzz/bundles
+ FRAMEWORK DESTINATION zzz/frameworks
+ )
+
+install(SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/check_installed.cmake")
diff --git a/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake
new file mode 100644
index 000000000..054ce9cc0
--- /dev/null
+++ b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake
@@ -0,0 +1,38 @@
+include("${CMAKE_CURRENT_LIST_DIR}/../check_installed.cmake")
+
+if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
+ set(_dirs [[aaa;aaa/executables;aaa/executables/testExe1-4;aaa/executables/testExe3;aaa/libraries;aaa/libraries/libtestExe2lib\.so;aaa/libraries/libtestLib3lib(-d|-r)?\.so\.1\.2;aaa/libraries/libtestLib3lib(-d|-r)?\.so\.3;aaa/libraries/libtestLib4\.so;aaa/libraries/libtestMod1\.so;aaa/libraries/libtestMod2\.so]])
+ set(_alldest [[bbb;bbb/libtestExe2lib\.so;bbb/libtestLib3lib(-d|-r)?\.so\.1\.2;bbb/libtestLib3lib(-d|-r)?\.so\.3;bbb/libtestLib4\.so;bbb/libtestMod1\.so;bbb/libtestMod2\.so;bbb/testExe1-4;bbb/testExe3]])
+ set(_default [[bin;bin/testExe1-4;bin/testExe3;lib;lib/libtestExe2lib\.so;lib/libtestLib3lib(-d|-r)?\.so\.1\.2;lib/libtestLib3lib(-d|-r)?\.so\.3;lib/libtestLib4\.so;lib/libtestMod1\.so;lib/libtestMod2\.so]])
+ check_installed("^${_dirs};${_alldest};${_default}$")
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+ set(_dirs_msvc [[aaa;aaa/executables;aaa/executables/testExe1\.exe;aaa/executables/testExe2lib\.dll;aaa/executables/testExe3\.exe;aaa/executables/testLib3dll(-d|-r)?\.dll;aaa/executables/testLib4\.dll;aaa/libraries;aaa/libraries/testMod1\.dll;aaa/libraries/testMod2\.dll]])
+ set(_dirs_mingw [[aaa;aaa/executables;aaa/executables/libtestExe2lib\.dll;aaa/executables/libtestLib3dll(-d|-r)?\.dll;aaa/executables/libtestLib4\.dll;aaa/executables/testExe1\.exe;aaa/executables/testExe3\.exe;aaa/libraries;aaa/libraries/libtestMod1\.dll;aaa/libraries/libtestMod2\.dll]])
+
+ set(_alldest_msvc [[bbb;bbb/testExe1\.exe;bbb/testExe2lib\.dll;bbb/testExe3\.exe;bbb/testLib3dll(-d|-r)?\.dll;bbb/testLib4\.dll;bbb/testMod1\.dll;bbb/testMod2\.dll]])
+ set(_alldest_mingw [[bbb;bbb/libtestExe2lib\.dll;bbb/libtestLib3dll(-d|-r)?\.dll;bbb/libtestLib4\.dll;bbb/libtestMod1\.dll;bbb/libtestMod2\.dll;bbb/testExe1\.exe;bbb/testExe3\.exe]])
+
+ set(_default_msvc [[bin;bin/testExe1\.exe;bin/testExe2lib\.dll;bin/testExe3\.exe;bin/testLib3dll(-d|-r)?\.dll;bin/testLib4\.dll;lib;lib/testMod1\.dll;lib/testMod2\.dll]])
+ set(_default_mingw [[bin;bin/libtestExe2lib\.dll;bin/libtestLib3dll(-d|-r)?\.dll;bin/libtestLib4\.dll;bin/testExe1\.exe;bin/testExe3\.exe;lib;lib/libtestMod1\.dll;lib/libtestMod2\.dll]])
+
+ check_installed("^(${_dirs_msvc};${_alldest_msvc};${_default_msvc}|${_dirs_mingw};${_alldest_mingw};${_default_mingw})$")
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
+ set(_bundles [[aaa/bundles;aaa/bundles/testExe3\.app;aaa/bundles/testExe3\.app/Contents;aaa/bundles/testExe3\.app/Contents/Info\.plist;aaa/bundles/testExe3\.app/Contents/MacOS;aaa/bundles/testExe3\.app/Contents/MacOS/testExe3(;aaa/bundles/testExe3\.app/Contents/PkgInfo)?(;aaa/bundles/testExe3\.app/Contents/_CodeSignature;aaa/bundles/testExe3\.app/Contents/_CodeSignature/CodeResources)?]])
+ set(_executables [[aaa/executables;aaa/executables/testExe1(-4)?]])
+ set(_frameworks [[aaa/frameworks;aaa/frameworks/testLib4\.framework;aaa/frameworks/testLib4\.framework/Headers;aaa/frameworks/testLib4\.framework/Headers/testLib4\.h;aaa/frameworks/testLib4\.framework/Resources;aaa/frameworks/testLib4\.framework/Versions;aaa/frameworks/testLib4\.framework/Versions/A;aaa/frameworks/testLib4\.framework/Versions/A/Resources;aaa/frameworks/testLib4\.framework/Versions/A/Resources/Info\.plist(;aaa/frameworks/testLib4\.framework/Versions/A/_CodeSignature;aaa/frameworks/testLib4\.framework/Versions/A/_CodeSignature/CodeResources)?;aaa/frameworks/testLib4\.framework/Versions/A/testLib4;aaa/frameworks/testLib4\.framework/Versions/Current;aaa/frameworks/testLib4\.framework/testLib4]])
+ set(_libraries [[aaa/libraries;aaa/libraries/libtestExe2lib\.dylib;aaa/libraries/libtestLib3lib(-d|-r)?\.1\.2\.dylib;aaa/libraries/libtestLib3lib(-d|-r)?\.3\.dylib;aaa/libraries/libtestMod1\.so;aaa/libraries/testMod2\.bundle;aaa/libraries/testMod2\.bundle/Contents;aaa/libraries/testMod2\.bundle/Contents/Info\.plist;aaa/libraries/testMod2\.bundle/Contents/MacOS;aaa/libraries/testMod2\.bundle/Contents/MacOS/testMod2(;aaa/libraries/testMod2\.bundle/Contents/_CodeSignature;aaa/libraries/testMod2\.bundle/Contents/_CodeSignature/CodeResources)?]])
+ set(_dirs "aaa;${_bundles};${_executables};${_frameworks};${_libraries}")
+
+ set(_alldest [[bbb;bbb/libtestExe2lib\.dylib;bbb/libtestLib3lib(-d|-r)?\.1\.2\.dylib;bbb/libtestLib3lib(-d|-r)?\.3\.dylib;bbb/libtestMod1\.so;bbb/testExe1(-4)?;bbb/testExe3\.app;bbb/testExe3\.app/Contents;bbb/testExe3\.app/Contents/Info\.plist;bbb/testExe3\.app/Contents/MacOS;bbb/testExe3\.app/Contents/MacOS/testExe3(;bbb/testExe3\.app/Contents/PkgInfo)?(;bbb/testExe3\.app/Contents/_CodeSignature;bbb/testExe3\.app/Contents/_CodeSignature/CodeResources)?;bbb/testLib4\.framework;bbb/testLib4\.framework/Headers;bbb/testLib4\.framework/Headers/testLib4\.h;bbb/testLib4\.framework/Resources;bbb/testLib4\.framework/Versions;bbb/testLib4\.framework/Versions/A;bbb/testLib4\.framework/Versions/A/Resources;bbb/testLib4\.framework/Versions/A/Resources/Info\.plist(;bbb/testLib4\.framework/Versions/A/_CodeSignature;bbb/testLib4\.framework/Versions/A/_CodeSignature/CodeResources)?;bbb/testLib4\.framework/Versions/A/testLib4;bbb/testLib4\.framework/Versions/Current;bbb/testLib4\.framework/testLib4;bbb/testMod2\.bundle;bbb/testMod2\.bundle/Contents;bbb/testMod2\.bundle/Contents/Info\.plist;bbb/testMod2\.bundle/Contents/MacOS;bbb/testMod2\.bundle/Contents/MacOS/testMod2(;bbb/testMod2\.bundle/Contents/_CodeSignature;bbb/testMod2\.bundle/Contents/_CodeSignature/CodeResources)?]])
+
+ set(_default_bin [[bin;bin/testExe1(-4)?]])
+ set(_default_lib [[lib;lib/libtestExe2lib\.dylib;lib/libtestLib3lib(-d|-r)?\.1\.2\.dylib;lib/libtestLib3lib(-d|-r)?\.3\.dylib;lib/libtestMod1\.so;lib/testMod2\.bundle;lib/testMod2\.bundle/Contents;lib/testMod2\.bundle/Contents/Info\.plist;lib/testMod2\.bundle/Contents/MacOS;lib/testMod2\.bundle/Contents/MacOS/testMod2(;lib/testMod2\.bundle/Contents/_CodeSignature;lib/testMod2\.bundle/Contents/_CodeSignature/CodeResources)?]])
+ set(_default_bundles [[zzz/bundles;zzz/bundles/testExe3\.app;zzz/bundles/testExe3\.app/Contents;zzz/bundles/testExe3\.app/Contents/Info\.plist;zzz/bundles/testExe3\.app/Contents/MacOS;zzz/bundles/testExe3\.app/Contents/MacOS/testExe3(;zzz/bundles/testExe3\.app/Contents/PkgInfo)?(;zzz/bundles/testExe3\.app/Contents/_CodeSignature;zzz/bundles/testExe3\.app/Contents/_CodeSignature/CodeResources)?]])
+ set(_default_frameworks [[zzz/frameworks;zzz/frameworks/testLib4\.framework;zzz/frameworks/testLib4\.framework/Headers;zzz/frameworks/testLib4\.framework/Headers/testLib4\.h;zzz/frameworks/testLib4\.framework/Resources;zzz/frameworks/testLib4\.framework/Versions;zzz/frameworks/testLib4\.framework/Versions/A;zzz/frameworks/testLib4\.framework/Versions/A/Resources;zzz/frameworks/testLib4\.framework/Versions/A/Resources/Info\.plist(;zzz/frameworks/testLib4\.framework/Versions/A/_CodeSignature;zzz/frameworks/testLib4\.framework/Versions/A/_CodeSignature/CodeResources)?;zzz/frameworks/testLib4\.framework/Versions/A/testLib4;zzz/frameworks/testLib4\.framework/Versions/Current;zzz/frameworks/testLib4\.framework/testLib4]])
+ set(_default "${_default_bin};${_default_lib};zzz;${_default_bundles};${_default_frameworks}")
+
+ # Need to break this up due to too many pairs of parentheses
+ check_installed("^${_dirs};bbb;")
+ check_installed(";${_alldest};bin;")
+ check_installed(";${_default}$")
+endif()
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/CMakeLists.txt b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/CMakeLists.txt
new file mode 100644
index 000000000..d1c4ff2f9
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/CMakeLists.txt
@@ -0,0 +1,74 @@
+set(CMAKE_SKIP_RPATH OFF)
+
+# Import targets from the install tree.
+include(${Import_BINARY_DIR}/../Root/install-RUNTIME_DEPENDENCY_SET/targets.cmake)
+
+add_executable(exe1 main.c)
+add_executable(exe2 main.c)
+
+if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set_target_properties(exe1 exe2 PROPERTIES
+ # Multiple MACOSX_BUNDLE executables are allowed on non-macOS platforms.
+ MACOSX_BUNDLE TRUE
+ )
+endif()
+
+add_library(sublib1 SHARED sublib1.c)
+target_link_libraries(sublib1 PRIVATE dep6)
+
+add_library(sublib2 SHARED sublib2.c)
+target_link_libraries(sublib2 PRIVATE dep7)
+
+foreach(i exe1 exe2)
+ target_link_libraries(${i} PRIVATE
+ dep1
+ dep2
+ dep3
+ dep4
+ dep5
+ dep10
+ dep11
+ dep12
+ sublib1
+ sublib2
+ )
+endforeach()
+
+add_library(lib SHARED lib.c)
+target_link_libraries(lib PRIVATE dep8)
+
+add_library(mod MODULE mod.c)
+target_link_libraries(mod PRIVATE dep9)
+if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set_target_properties(mod PROPERTIES
+ SKIP_BUILD_RPATH TRUE
+ )
+endif()
+
+set(_framework_args)
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(_framework_args FRAMEWORK DESTINATION subdir/frameworks)
+endif()
+install(TARGETS exe1 exe2 lib mod sublib1
+ RUNTIME_DEPENDENCIES
+ PRE_INCLUDE_REGEXES "$<1:dep([2-9]|1[012])>"
+ PRE_EXCLUDE_REGEXES "$<1:.*>"
+ POST_INCLUDE_REGEXES "$<1:(bin|lib)/(lib)?dep3>"
+ POST_EXCLUDE_REGEXES "$<1:(bin|lib)/(lib)?dep[34]>"
+ POST_INCLUDE_FILES "$<TARGET_FILE:dep10>" "$<TARGET_FILE:dep11>"
+ POST_EXCLUDE_FILES "$<TARGET_FILE:dep11>" "$<TARGET_FILE:dep12>"
+ DIRECTORIES "$<TARGET_FILE_DIR:dep9>"
+ RUNTIME DESTINATION "$<1:subdir/bin>"
+ LIBRARY DESTINATION "$<1:subdir/lib>"
+ ${_framework_args}
+ )
+
+install(TARGETS lib
+ RUNTIME_DEPENDENCIES
+ PRE_INCLUDE_REGEXES dep8
+ PRE_EXCLUDE_REGEXES ".*"
+ DIRECTORIES "$<TARGET_FILE_DIR:dep8>"
+ ${_framework_args}
+ )
+
+install(SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/check_installed.cmake")
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/check_installed.cmake b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/check_installed.cmake
new file mode 100644
index 000000000..6a34697f8
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/check_installed.cmake
@@ -0,0 +1,11 @@
+include("${CMAKE_CURRENT_LIST_DIR}/../check_installed.cmake")
+
+if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
+ check_installed([[^lib;lib/libdep8\.so;lib/liblib\.so;subdir;subdir/bin;subdir/bin/exe1;subdir/bin/exe2;subdir/lib;subdir/lib/libdep10\.so;subdir/lib/libdep11\.so;subdir/lib/libdep2\.so\.1;subdir/lib/libdep2\.so\.1\.2\.3;subdir/lib/libdep3\.so;subdir/lib/libdep5\.so;subdir/lib/libdep6\.so;subdir/lib/libdep8\.so;subdir/lib/libdep9\.so;subdir/lib/liblib\.so;subdir/lib/libmod\.so;subdir/lib/libsublib1\.so$]])
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+ set(_msvc_check [[bin;bin/dep8\.dll;bin/lib\.dll;lib;lib/lib\.lib;subdir;subdir/bin;subdir/bin/dep10\.dll;subdir/bin/dep11\.dll;subdir/bin/dep2\.dll;subdir/bin/dep3\.dll;subdir/bin/dep5\.dll;subdir/bin/dep6\.dll;subdir/bin/dep8\.dll;subdir/bin/dep9\.dll;subdir/bin/exe1\.exe;subdir/bin/exe2\.exe;subdir/bin/lib\.dll;subdir/bin/sublib1\.dll;subdir/lib;subdir/lib/mod\.dll]])
+ set(_mingw_check [[bin;bin/libdep8\.dll;bin/liblib\.dll;lib;lib/liblib\.dll\.a;lib/liblib\.lib;subdir;subdir/bin;subdir/bin/exe1\.exe;subdir/bin/exe2\.exe;subdir/bin/libdep10\.dll;subdir/bin/libdep11\.dll;subdir/bin/libdep2\.dll;subdir/bin/libdep3\.dll;subdir/bin/libdep5\.dll;subdir/bin/libdep6\.dll;subdir/bin/libdep8\.dll;subdir/bin/libdep9\.dll;subdir/bin/liblib\.dll;subdir/bin/libsublib1\.dll;subdir/lib;subdir/lib/libmod\.dll]])
+ check_installed("^(${_msvc_check}|${_mingw_check})$")
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
+ check_installed([[^lib;lib/libdep8\.dylib;lib/liblib\.dylib;subdir;subdir/bin;subdir/bin/exe1;subdir/bin/exe2;subdir/frameworks;subdir/frameworks/dep9\.framework;subdir/frameworks/dep9\.framework/Resources;subdir/frameworks/dep9\.framework/Versions;subdir/frameworks/dep9\.framework/Versions/A;subdir/frameworks/dep9\.framework/Versions/A/Resources;subdir/frameworks/dep9\.framework/Versions/A/Resources/Info\.plist(;subdir/frameworks/dep9.framework/Versions/A/_CodeSignature;subdir/frameworks/dep9.framework/Versions/A/_CodeSignature/CodeResources)?;subdir/frameworks/dep9\.framework/Versions/A/dep9;subdir/frameworks/dep9\.framework/Versions/Current;subdir/frameworks/dep9\.framework/dep9;subdir/lib;subdir/lib/libdep10\.dylib;subdir/lib/libdep11\.dylib;subdir/lib/libdep2\.1\.2\.3\.dylib;subdir/lib/libdep2\.1\.dylib;subdir/lib/libdep3\.dylib;subdir/lib/libdep5\.dylib;subdir/lib/libdep6\.dylib;subdir/lib/libdep8\.dylib;subdir/lib/liblib\.dylib;subdir/lib/libmod\.so;subdir/lib/libsublib1\.dylib$]])
+endif()
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/lib.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/lib.c
new file mode 100644
index 000000000..9a648874b
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/lib.c
@@ -0,0 +1,12 @@
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ extern void dep8(void);
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void lib(void)
+{
+ dep8();
+}
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/main.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/main.c
new file mode 100644
index 000000000..94a7862d4
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/main.c
@@ -0,0 +1,31 @@
+#ifdef _WIN32
+# define DLLIMPORT __declspec(dllimport)
+#else
+# define DLLIMPORT
+#endif
+
+DLLIMPORT extern void dep1(void);
+DLLIMPORT extern void dep2(void);
+DLLIMPORT extern void dep3(void);
+DLLIMPORT extern void dep4(void);
+DLLIMPORT extern void dep5(void);
+DLLIMPORT extern void dep10(void);
+DLLIMPORT extern void dep11(void);
+DLLIMPORT extern void dep12(void);
+DLLIMPORT extern void sublib1(void);
+DLLIMPORT extern void sublib2(void);
+
+int main(void)
+{
+ dep1();
+ dep2();
+ dep3();
+ dep4();
+ dep5();
+ dep10();
+ dep11();
+ dep12();
+ sublib1();
+ sublib2();
+ return 0;
+}
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/mod.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/mod.c
new file mode 100644
index 000000000..d001299bd
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/mod.c
@@ -0,0 +1,12 @@
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ extern void dep9(void);
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void mod(void)
+{
+ dep9();
+}
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib1.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib1.c
new file mode 100644
index 000000000..f17b9026e
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib1.c
@@ -0,0 +1,12 @@
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ extern void dep6(void);
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void sublib1(void)
+{
+ dep6();
+}
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib2.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib2.c
new file mode 100644
index 000000000..61b5c8395
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib2.c
@@ -0,0 +1,12 @@
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ extern void dep7(void);
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void sublib2(void)
+{
+ dep7();
+}
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt
new file mode 100644
index 000000000..516450644
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt
@@ -0,0 +1,33 @@
+set(CMAKE_SKIP_RPATH OFF)
+
+# Import targets from the install tree.
+include(${Import_BINARY_DIR}/../Root/install-RUNTIME_DEPENDENCY_SET/targets.cmake)
+
+add_executable(exe main.c)
+target_link_libraries(exe PRIVATE dep3 dep4)
+
+install(TARGETS exe RUNTIME_DEPENDENCY_SET myset)
+install(IMPORTED_RUNTIME_ARTIFACTS deplib RUNTIME_DEPENDENCY_SET myset)
+
+install(RUNTIME_DEPENDENCY_SET myset
+ PRE_INCLUDE_REGEXES "dep[134]"
+ PRE_EXCLUDE_REGEXES ".*"
+ POST_INCLUDE_REGEXES "dep[13]"
+ POST_EXCLUDE_REGEXES "dep[34]"
+ DIRECTORIES "$<TARGET_FILE_DIR:dep1>"
+ )
+install(RUNTIME_DEPENDENCY_SET myset
+ PRE_INCLUDE_REGEXES "dep[134]"
+ PRE_EXCLUDE_REGEXES ".*"
+ DIRECTORIES "$<TARGET_FILE_DIR:dep1>"
+ RUNTIME DESTINATION yyy/bin
+ LIBRARY DESTINATION yyy/lib
+ )
+install(RUNTIME_DEPENDENCY_SET myset
+ PRE_INCLUDE_REGEXES "dep[134]"
+ PRE_EXCLUDE_REGEXES ".*"
+ DIRECTORIES "$<TARGET_FILE_DIR:dep1>"
+ DESTINATION zzz
+ )
+
+install(SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/check_installed.cmake")
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/check_installed.cmake b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/check_installed.cmake
new file mode 100644
index 000000000..052ccede5
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/check_installed.cmake
@@ -0,0 +1,11 @@
+include("${CMAKE_CURRENT_LIST_DIR}/../check_installed.cmake")
+
+if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
+ check_installed([[^bin;bin/exe;lib;lib/libdep1\.so;lib/libdep3\.so;lib/libdeplib\.so;yyy;yyy/lib;yyy/lib/libdep1\.so;yyy/lib/libdep3\.so;yyy/lib/libdep4\.so;zzz;zzz/libdep1\.so;zzz/libdep3\.so;zzz/libdep4\.so$]])
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+ set(_msvc_check [[bin;bin/dep1\.dll;bin/dep3\.dll;bin/deplib\.dll;bin/exe\.exe;yyy;yyy/bin;yyy/bin/dep1\.dll;yyy/bin/dep3\.dll;yyy/bin/dep4\.dll;zzz;zzz/dep1\.dll;zzz/dep3\.dll;zzz/dep4\.dll]])
+ set(_mingw_check [[bin;bin/exe\.exe;bin/libdep1\.dll;bin/libdep3\.dll;bin/libdeplib\.dll;yyy;yyy/bin;yyy/bin/libdep1\.dll;yyy/bin/libdep3\.dll;yyy/bin/libdep4\.dll;zzz;zzz/libdep1\.dll;zzz/libdep3\.dll;zzz/libdep4\.dll]])
+ check_installed("^(${_msvc_check}|${_mingw_check})$")
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
+ check_installed([[^bin;bin/exe;lib;lib/libdep1\.dylib;lib/libdep3\.dylib;lib/libdeplib\.dylib;yyy;yyy/lib;yyy/lib/libdep1\.dylib;yyy/lib/libdep3\.dylib;yyy/lib/libdep4\.dylib;zzz;zzz/libdep1\.dylib;zzz/libdep3\.dylib;zzz/libdep4\.dylib$]])
+endif()
diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/main.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/main.c
new file mode 100644
index 000000000..b359498b7
--- /dev/null
+++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/main.c
@@ -0,0 +1,15 @@
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ extern void dep3(void);
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ extern void dep4(void);
+
+int main(void)
+{
+ dep3();
+ dep4();
+ return 0;
+}
diff --git a/Tests/ExternalProjectLocal/CMakeLists.txt b/Tests/ExternalProjectLocal/CMakeLists.txt
index 9a0241c27..57e81052b 100644
--- a/Tests/ExternalProjectLocal/CMakeLists.txt
+++ b/Tests/ExternalProjectLocal/CMakeLists.txt
@@ -41,7 +41,7 @@ set(TutorialStep5_install_dir ${install_dir})
set(proj TutorialStep5-Local-TestAfterInstall)
ExternalProject_Add(${proj}
URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
-CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+CMAKE_ARGS --install-prefix=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
TEST_AFTER_INSTALL 1
LOG_TEST 1
@@ -51,7 +51,7 @@ set_property(TARGET ${proj} PROPERTY FOLDER "Local")
set(proj TutorialStep5-Local-TestExcludeFromMainBefore)
ExternalProject_Add(${proj}
URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
-CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+CMAKE_ARGS --install-prefix=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
TEST_BEFORE_INSTALL 1
TEST_EXCLUDE_FROM_MAIN 1
@@ -63,7 +63,7 @@ set_property(TARGET ${proj} PROPERTY FOLDER "Local")
set(proj TutorialStep5-Local-TestExcludeFromMainAfter)
ExternalProject_Add(${proj}
URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
-CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+CMAKE_ARGS --install-prefix=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
TEST_AFTER_INSTALL 1
TEST_EXCLUDE_FROM_MAIN 1
diff --git a/Tests/FindBLAS/CMakeLists.txt b/Tests/FindBLAS/CMakeLists.txt
index 667195dd9..482cee876 100644
--- a/Tests/FindBLAS/CMakeLists.txt
+++ b/Tests/FindBLAS/CMakeLists.txt
@@ -1,10 +1,49 @@
-add_test(NAME FindBLAS.Test COMMAND
- ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test"
- "${CMake_BINARY_DIR}/Tests/FindBLAS/Test"
- ${build_generator_args}
- --build-project TestFindBLAS
- --build-options ${build_options}
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
- )
+foreach(variant IN LISTS CMake_TEST_FindBLAS)
+ if(variant MATCHES "^([^.]+)\\.(.*)$")
+ set(vendor "${CMAKE_MATCH_1}")
+ set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}")
+ else()
+ set(vendor "${variant}")
+ set(alt_compiler "")
+ endif()
+ if(vendor STREQUAL "All" AND CMake_TEST_FindBLAS_All)
+ set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindBLAS_All}")
+ else()
+ set(EXPECT_All "")
+ endif()
+ add_test(NAME FindBLAS.Test_${variant} COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test"
+ "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}"
+ ${build_generator_args}
+ --build-project TestFindBLAS
+ --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+endforeach()
+
+foreach(variant IN LISTS CMake_TEST_FindBLAS_STATIC)
+ if(variant MATCHES "^([^.]+)\\.(.*)$")
+ set(vendor "${CMAKE_MATCH_1}")
+ set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}")
+ else()
+ set(vendor "${variant}")
+ set(alt_compiler "")
+ endif()
+ if(vendor STREQUAL "All" AND CMake_TEST_FindBLAS_STATIC_All)
+ set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindBLAS_STATIC_All}")
+ else()
+ set(EXPECT_All "")
+ endif()
+ add_test(NAME FindBLAS.Test_${variant}_Static COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test"
+ "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}_Static"
+ ${build_generator_args}
+ --build-project TestFindBLAS
+ --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+endforeach()
diff --git a/Tests/FindBLAS/Test/CMakeLists.txt b/Tests/FindBLAS/Test/CMakeLists.txt
index 59418f34a..73797496a 100644
--- a/Tests/FindBLAS/Test/CMakeLists.txt
+++ b/Tests/FindBLAS/Test/CMakeLists.txt
@@ -11,3 +11,10 @@ add_test(NAME test_tgt COMMAND test_tgt)
add_executable(test_var main.c)
target_link_libraries(test_var PRIVATE ${BLAS_LIBRARIES})
add_test(NAME test_var COMMAND test_var)
+
+if((BLA_VENDOR STREQUAL "Intel10_64lp") OR
+ (BLA_VENDOR STREQUAL "All" AND EXPECT_All STREQUAL "Intel10_64lp"))
+ if(NOT BLAS_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64")
+ message(FATAL_ERROR "BLAS_LIBRARIES does not start in mkl_intel_lp64:\n ${BLAS_LIBRARIES}")
+ endif()
+endif()
diff --git a/Tests/FindDevIL/CMakeLists.txt b/Tests/FindDevIL/CMakeLists.txt
new file mode 100644
index 000000000..d37d50faf
--- /dev/null
+++ b/Tests/FindDevIL/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindDevIL.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindDevIL/Test"
+ "${CMake_BINARY_DIR}/Tests/FindDevIL/Test"
+ ${build_generator_args}
+ --build-project TestFindDevIL
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindDevIL/Test/CMakeLists.txt b/Tests/FindDevIL/Test/CMakeLists.txt
new file mode 100644
index 000000000..c2c132223
--- /dev/null
+++ b/Tests/FindDevIL/Test/CMakeLists.txt
@@ -0,0 +1,29 @@
+cmake_minimum_required(VERSION 3.1)
+project(TestFindDevIL C)
+include(CTest)
+
+find_package(DevIL)
+
+#FIXME: check version too.
+# add_definitions(
+# -DCMAKE_EXPECTED_SDL_VERSION_MAJOR=${SDL_VERSION_MAJOR}
+# -DCMAKE_EXPECTED_SDL_VERSION_MINOR=${SDL_VERSION_MINOR}
+# -DCMAKE_EXPECTED_SDL_VERSION_PATCH=${SDL_VERSION_PATCH})
+
+add_executable(test_devil_var main.c)
+target_include_directories(test_devil_var PRIVATE ${IL_INCLUDE_DIRS})
+target_link_libraries(test_devil_var PRIVATE ${IL_LIBRARIES})
+add_test(NAME test_devil_var COMMAND test_devil_var)
+
+add_executable(test_devil_il_tgt main.c)
+target_link_libraries(test_devil_il_tgt DevIL::IL)
+add_test(NAME test_devil_il_tgt COMMAND test_devil_il_tgt)
+
+add_executable(test_devil_ilu_tgt main_ilu.c)
+target_link_libraries(test_devil_ilu_tgt DevIL::ILU)
+
+add_executable(test_devil_ilu_var main_ilu.c)
+target_include_directories(test_devil_ilu_var PRIVATE ${IL_INCLUDE_DIRS} ${ILU_INCLUDE_DIRS})
+target_link_libraries(test_devil_ilu_var ${IL_LIBRARIES} ${ILU_LIBRARIES})
+
+#FIXME: Check DevIL::ILUT target
diff --git a/Tests/FindDevIL/Test/main.c b/Tests/FindDevIL/Test/main.c
new file mode 100644
index 000000000..4a0708720
--- /dev/null
+++ b/Tests/FindDevIL/Test/main.c
@@ -0,0 +1,10 @@
+#include <IL/il.h>
+
+int main()
+{
+ // Test 1 requires to link to the library.
+ ilInit();
+
+ ilShutDown();
+ return 0;
+}
diff --git a/Tests/FindDevIL/Test/main_ilu.c b/Tests/FindDevIL/Test/main_ilu.c
new file mode 100644
index 000000000..a9e7819ba
--- /dev/null
+++ b/Tests/FindDevIL/Test/main_ilu.c
@@ -0,0 +1,8 @@
+#include <IL/ilu.h>
+
+int main()
+{
+ // IL Utilities requires only initialization.
+ // Unlike main DevIL there are no shutdown function.
+ iluInit();
+}
diff --git a/Tests/FindLAPACK/CMakeLists.txt b/Tests/FindLAPACK/CMakeLists.txt
index 2081d5924..535c7b60e 100644
--- a/Tests/FindLAPACK/CMakeLists.txt
+++ b/Tests/FindLAPACK/CMakeLists.txt
@@ -1,10 +1,49 @@
-add_test(NAME FindLAPACK.Test COMMAND
- ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test"
- "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test"
- ${build_generator_args}
- --build-project TestFindLAPACK
- --build-options ${build_options}
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
- )
+foreach(variant IN LISTS CMake_TEST_FindLAPACK)
+ if(variant MATCHES "^([^.]+)\\.(.*)$")
+ set(vendor "${CMAKE_MATCH_1}")
+ set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}")
+ else()
+ set(vendor "${variant}")
+ set(alt_compiler "")
+ endif()
+ if(vendor STREQUAL "All" AND CMake_TEST_FindLAPACK_All)
+ set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindLAPACK_All}")
+ else()
+ set(EXPECT_All "")
+ endif()
+ add_test(NAME FindLAPACK.Test_${variant} COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test"
+ "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}"
+ ${build_generator_args}
+ --build-project TestFindLAPACK
+ --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+endforeach()
+
+foreach(variant IN LISTS CMake_TEST_FindLAPACK_STATIC)
+ if(variant MATCHES "^([^.]+)\\.(.*)$")
+ set(vendor "${CMAKE_MATCH_1}")
+ set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}")
+ else()
+ set(vendor "${variant}")
+ set(alt_compiler "")
+ endif()
+ if(vendor STREQUAL "All" AND CMake_TEST_FindLAPACK_STATIC_All)
+ set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindLAPACK_STATIC_All}")
+ else()
+ set(EXPECT_All "")
+ endif()
+ add_test(NAME FindLAPACK.Test_${variant}_Static COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test"
+ "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}_Static"
+ ${build_generator_args}
+ --build-project TestFindLAPACK
+ --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+endforeach()
diff --git a/Tests/FindLAPACK/Test/CMakeLists.txt b/Tests/FindLAPACK/Test/CMakeLists.txt
index 8afa36a12..23a43acec 100644
--- a/Tests/FindLAPACK/Test/CMakeLists.txt
+++ b/Tests/FindLAPACK/Test/CMakeLists.txt
@@ -11,3 +11,10 @@ add_test(NAME test_tgt COMMAND test_tgt)
add_executable(test_var main.c)
target_link_libraries(test_var PRIVATE ${LAPACK_LIBRARIES})
add_test(NAME test_var COMMAND test_var)
+
+if((BLA_VENDOR STREQUAL "Intel10_64lp") OR
+ (BLA_VENDOR STREQUAL "All" AND EXPECT_All STREQUAL "Intel10_64lp"))
+ if(NOT LAPACK_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64")
+ message(FATAL_ERROR "LAPACK_LIBRARIES does not start in mkl_intel_lp64:\n ${LAPACK_LIBRARIES}")
+ endif()
+endif()
diff --git a/Tests/FindPackageModeMakefileTest/CMakeLists.txt b/Tests/FindPackageModeMakefileTest/CMakeLists.txt
index 8a87a8c97..0b15be8cf 100644
--- a/Tests/FindPackageModeMakefileTest/CMakeLists.txt
+++ b/Tests/FindPackageModeMakefileTest/CMakeLists.txt
@@ -19,12 +19,16 @@ if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Makefile" AND
# configure a FindFoo.cmake so it knows where the library can be found
configure_file(FindFoo.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FindFoo.cmake @ONLY)
- # Need the -isysroot flag on recentish macOS after command line tools
- # no longer provide headers in /usr/include
- if(APPLE AND CMAKE_OSX_SYSROOT)
- set(__EXTRA_OSX_SYSROOT_FLAGS "-isysroot ${CMAKE_OSX_SYSROOT}")
- else()
- set(__EXTRA_OSX_SYSROOT_FLAGS "")
+ set(EXTRA_FLAGS "")
+ if(APPLE)
+ # Need the -isysroot flag on recentish macOS after command line tools
+ # no longer provide headers in /usr/include
+ if(CMAKE_OSX_SYSROOT)
+ string(APPEND EXTRA_FLAGS " -isysroot ${CMAKE_OSX_SYSROOT}")
+ endif()
+ foreach(arch ${CMAKE_OSX_ARCHITECTURES})
+ string(APPEND EXTRA_FLAGS " -arch ${arch}")
+ endforeach()
endif()
# now set up the test:
diff --git a/Tests/FindPackageModeMakefileTest/Makefile.in b/Tests/FindPackageModeMakefileTest/Makefile.in
index af9fa9609..695c64fe6 100644
--- a/Tests/FindPackageModeMakefileTest/Makefile.in
+++ b/Tests/FindPackageModeMakefileTest/Makefile.in
@@ -5,7 +5,7 @@ CMAKE_CURRENT_BINARY_DIR = "@CMAKE_CURRENT_BINARY_DIR@"
CMAKE_CXX_COMPILER = "@CMAKE_CXX_COMPILER@"
CMAKE_CXX_COMPILER_ID = "@CMAKE_CXX_COMPILER_ID@"
CMAKE_CXX_FLAGS = @CMAKE_CXX_FLAGS@
-__EXTRA_OSX_SYSROOT_FLAGS = @__EXTRA_OSX_SYSROOT_FLAGS@
+EXTRA_FLAGS = @EXTRA_FLAGS@
CMAKE_FOO = $(CMAKE) --find-package -DCMAKE_MODULE_PATH=$(CMAKE_CURRENT_BINARY_DIR) -DNAME=Foo -DLANGUAGE=CXX -DCOMPILER_ID=$(CMAKE_CXX_COMPILER_ID)
@@ -16,7 +16,7 @@ all: pngtest
main.o: clean main.cpp
@$(CMAKE_FOO) -DMODE=COMPILE >$(tmp)
@foo="`cat $(tmp)`"; \
- printf '"%s" %s %s %s -c main.cpp\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$(__EXTRA_OSX_SYSROOT_FLAGS)" "$$foo" >$(tmp)
+ printf '"%s" %s %s %s -c main.cpp\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$(EXTRA_FLAGS)" "$$foo" >$(tmp)
@cat $(tmp)
@sh $(tmp)
@rm -f $(tmp)
@@ -24,7 +24,7 @@ main.o: clean main.cpp
pngtest: main.o
@$(CMAKE_FOO) -DMODE=LINK >$(tmp)
@foo="`cat $(tmp)`"; \
- printf '"%s" %s %s %s -o pngtest main.o %s\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$(__EXTRA_OSX_SYSROOT_FLAGS)" "$(LDFLAGS)" "$$foo" >$(tmp)
+ printf '"%s" %s %s %s -o pngtest main.o %s\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$(EXTRA_FLAGS)" "$(LDFLAGS)" "$$foo" >$(tmp)
@cat $(tmp)
@sh $(tmp)
@rm -f $(tmp)
diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt
index 7217f43b6..c25b2c304 100644
--- a/Tests/FindPackageTest/CMakeLists.txt
+++ b/Tests/FindPackageTest/CMakeLists.txt
@@ -24,7 +24,7 @@ find_package(VTK QUIET)
add_executable(FindPackageTest FindPackageTest.cxx)
-# test behaviour of cmFindBase wrt. the CMAKE_PREFIX_PATH variable
+# test behavior of cmFindBase wrt. the CMAKE_PREFIX_PATH variable
# foo.h should be found in ${CMAKE_CURRENT_SOURCE_DIR}/include:
set(CMAKE_PREFIX_PATH /blub /blah "${CMAKE_CURRENT_SOURCE_DIR}")
@@ -189,7 +189,9 @@ find_package(ArchD 4.0 EXACT NAMES zot)
unset(CMAKE_LIBRARY_ARCHITECTURE)
# Test find_package() with CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS enabled
-if(UNIX)
+if(UNIX
+ AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS
+ )
# Create ./symlink pointing back here.
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
. "${CMAKE_CURRENT_SOURCE_DIR}/symlink")
diff --git a/Tests/FindProtobuf/CMakeLists.txt b/Tests/FindProtobuf/CMakeLists.txt
index 1cdb2ae13..b4ca29bc7 100644
--- a/Tests/FindProtobuf/CMakeLists.txt
+++ b/Tests/FindProtobuf/CMakeLists.txt
@@ -6,5 +6,6 @@ add_test(NAME FindProtobuf.Test COMMAND
${build_generator_args}
--build-project TestFindProtobuf
--build-options ${build_options}
+ "-DCMake_TEST_FindProtobuf_gRPC=${CMake_TEST_FindProtobuf_gRPC}"
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
diff --git a/Tests/FindProtobuf/Test/CMakeLists.txt b/Tests/FindProtobuf/Test/CMakeLists.txt
index fc6b37e95..84041eaf4 100644
--- a/Tests/FindProtobuf/Test/CMakeLists.txt
+++ b/Tests/FindProtobuf/Test/CMakeLists.txt
@@ -52,3 +52,16 @@ target_include_directories(test_desc PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(test_desc msgs ${Protobuf_LIBRARIES})
target_compile_features(test_desc PRIVATE cxx_std_11)
add_test(NAME test_desc COMMAND test_desc ${DESC_PROTO_DESC})
+
+if(CMake_TEST_FindProtobuf_gRPC)
+ find_program(gRPC_CPP_PLUGIN grpc_cpp_plugin)
+ add_library(msgs_grpc msgs/example_service.proto)
+ target_include_directories(msgs_grpc PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
+ target_link_libraries(msgs_grpc PUBLIC ${Protobuf_LIBRARIES})
+ protobuf_generate(TARGET msgs_grpc LANGUAGE cpp)
+ protobuf_generate(TARGET msgs_grpc LANGUAGE grpc GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=${gRPC_CPP_PLUGIN}")
+
+ add_executable(test_generate_grpc main-generate-grpc.cxx)
+ target_link_libraries(test_generate_grpc PRIVATE msgs_grpc)
+ add_test(NAME test_generate_grpc COMMAND test_generate_grpc)
+endif()
diff --git a/Tests/FindProtobuf/Test/main-generate-grpc.cxx b/Tests/FindProtobuf/Test/main-generate-grpc.cxx
new file mode 100644
index 000000000..070c6b46e
--- /dev/null
+++ b/Tests/FindProtobuf/Test/main-generate-grpc.cxx
@@ -0,0 +1,6 @@
+#include <msgs/example_service.grpc.pb.h>
+
+int main()
+{
+ return 0;
+}
diff --git a/Tests/FindProtobuf/Test/msgs/example_service.proto b/Tests/FindProtobuf/Test/msgs/example_service.proto
new file mode 100644
index 000000000..f35eeb538
--- /dev/null
+++ b/Tests/FindProtobuf/Test/msgs/example_service.proto
@@ -0,0 +1,8 @@
+syntax = "proto3";
+package example.msgs;
+
+import "google/protobuf/empty.proto";
+
+service ExampleService {
+ rpc nothing(google.protobuf.Empty) returns (google.protobuf.Empty) {}
+}
diff --git a/Tests/FindVulkan/Test/CMakeLists.txt b/Tests/FindVulkan/Test/CMakeLists.txt
index 9d36a0da3..7ae8a1104 100644
--- a/Tests/FindVulkan/Test/CMakeLists.txt
+++ b/Tests/FindVulkan/Test/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.4)
-project(TestFindVulkan C)
+project(TestFindVulkan C CXX)
include(CTest)
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../)
@@ -14,6 +14,15 @@ target_include_directories(test_var PRIVATE ${Vulkan_INCLUDE_DIRS})
target_link_libraries(test_var PRIVATE ${Vulkan_LIBRARIES})
add_test(NAME test_var COMMAND test_var)
+add_executable(test_tgt_dl main-dynamicVulkanLoading.cpp)
+target_link_libraries(test_tgt_dl Vulkan::Headers ${CMAKE_DL_LIBS})
+add_test(NAME test_tgt_dl COMMAND test_tgt_dl)
+
+add_executable(test_var_dl main-dynamicVulkanLoading.cpp)
+target_include_directories(test_var_dl PRIVATE ${Vulkan_INCLUDE_DIRS})
+target_link_libraries(test_var_dl ${CMAKE_DL_LIBS})
+add_test(NAME test_var_dl COMMAND test_var_dl)
+
if(Vulkan_GLSLC_EXECUTABLE)
add_test(NAME test_glslc
COMMAND ${CMAKE_COMMAND}
@@ -22,3 +31,12 @@ if(Vulkan_GLSLC_EXECUTABLE)
-P "${CMAKE_CURRENT_LIST_DIR}/Run-glslc.cmake"
)
endif()
+
+if(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE)
+ add_test(NAME test_glslangValidator
+ COMMAND ${CMAKE_COMMAND}
+ "-DVULKAN_GLSLANG_VALIDATOR_EXECUTABLE=${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE}"
+ "-DVULKAN_GLSLANG_VALIDATOR_EXECUTABLE_TARGET=$<TARGET_FILE:Vulkan::glslangValidator>"
+ -P "${CMAKE_CURRENT_LIST_DIR}/Run-glslangValidator.cmake"
+ )
+endif()
diff --git a/Tests/FindVulkan/Test/Run-glslangValidator.cmake b/Tests/FindVulkan/Test/Run-glslangValidator.cmake
new file mode 100644
index 000000000..27fd9503d
--- /dev/null
+++ b/Tests/FindVulkan/Test/Run-glslangValidator.cmake
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.12)
+
+function(run_glslangValidator exe exe_display)
+ execute_process(COMMAND ${exe} --help
+ OUTPUT_VARIABLE output
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE result
+ )
+
+ if(NOT result EQUAL 1)
+ message(SEND_ERROR "Result of ${exe_display} --help is ${result}, should be 1")
+ endif()
+
+ if(NOT output MATCHES "^Usage: glslangValidator")
+ message(SEND_ERROR "Output of ${exe_display} --help is \"${output}\", should begin with \"Usage: glslangValidator\"")
+ endif()
+endfunction()
+
+run_glslangValidator("${VULKAN_GLSLANG_VALIDATOR_EXECUTABLE}" "\${VULKAN_GLSLANG_VALIDATOR_EXECUTABLE}")
+run_glslangValidator("${VULKAN_GLSLANG_VALIDATOR_EXECUTABLE_TARGET}" "Vulkan::glslangValidator")
diff --git a/Tests/FindVulkan/Test/main-dynamicVulkanLoading.cpp b/Tests/FindVulkan/Test/main-dynamicVulkanLoading.cpp
new file mode 100644
index 000000000..f6f909fe1
--- /dev/null
+++ b/Tests/FindVulkan/Test/main-dynamicVulkanLoading.cpp
@@ -0,0 +1,55 @@
+#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
+
+#include <iostream>
+
+#include <vulkan/vulkan.hpp>
+
+using namespace std;
+
+VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
+
+int main()
+{
+ // catch exceptions
+ // (vulkan.hpp functions throws if they fail)
+ try {
+
+ // initialize dynamic dispatcher
+ vk::DynamicLoader dl;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
+ dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
+ VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
+
+ // Vulkan instance
+ vk::UniqueInstance instance =
+ vk::createInstanceUnique(vk::InstanceCreateInfo{
+ vk::InstanceCreateFlags(), // flags
+ &(const vk::ApplicationInfo&)vk::ApplicationInfo{
+ "CMake Test application", // application name
+ VK_MAKE_VERSION(0, 0, 0), // application version
+ "CMake Test Engine", // engine name
+ VK_MAKE_VERSION(0, 0, 0), // engine version
+ VK_API_VERSION_1_0, // api version
+ },
+ 0, // enabled layer count
+ nullptr, // enabled layer names
+ 0, // enabled extension count
+ nullptr, // enabled extension names
+ });
+ VULKAN_HPP_DEFAULT_DISPATCHER.init(instance.get());
+
+ // catch exceptions
+ } catch (vk::Error& e) {
+ cout << "Failed because of Vulkan exception: " << e.what() << endl;
+ } catch (exception& e) {
+ cout << "Failed because of exception: " << e.what() << endl;
+ } catch (...) {
+ cout << "Failed because of unspecified exception." << endl;
+ }
+
+ // We can't assert in this code because in general vk::createInstanceUnique
+ // might throw if no driver is found - but if we get here, FindVulkan is
+ // working
+
+ return 0;
+}
diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt
index 18688923f..2fc47a519 100644
--- a/Tests/Fortran/CMakeLists.txt
+++ b/Tests/Fortran/CMakeLists.txt
@@ -46,7 +46,7 @@ function(test_fortran_c_interface_module)
FortranCInterface_VERIFY()
FortranCInterface_VERIFY(CXX)
if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
- if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "SunPro|PathScale|Absoft")
+ if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "SunPro|PathScale|Absoft|Fujitsu")
set(module_expected 1)
endif()
if(FortranCInterface_MODULE_FOUND OR module_expected)
@@ -131,7 +131,7 @@ else()
# as a language, cmake needs language specific versions
# of these variables....
if(WIN32 AND CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
- set(CMAKE_CREATE_CONSOLE_EXE )
+ set(CMAKE_Fortran_CREATE_CONSOLE_EXE )
set(CMAKE_LIBRARY_PATH_FLAG "-L")
set(CMAKE_LINK_LIBRARY_FLAG "-l")
set(CMAKE_LINK_LIBRARY_SUFFIX )
diff --git a/Tests/FortranModules/CMakeLists.txt b/Tests/FortranModules/CMakeLists.txt
index b7a6f6832..94f593908 100644
--- a/Tests/FortranModules/CMakeLists.txt
+++ b/Tests/FortranModules/CMakeLists.txt
@@ -1,6 +1,11 @@
cmake_minimum_required (VERSION 3.9)
project(FortranModules Fortran)
+if("${CMAKE_Fortran_COMPILER_ID};${CMAKE_Fortran_SIMULATE_ID}" MATCHES "^Intel(LLVM)?;MSVC$")
+ string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -Z7")
+ string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO " -Z7")
+endif()
+
if(NOT DEFINED CMake_TEST_NESTED_MAKE_PROGRAM AND NOT CMAKE_GENERATOR MATCHES "Visual Studio")
set(CMake_TEST_NESTED_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM}")
endif()
diff --git a/Tests/FortranOnly/CMakeLists.txt b/Tests/FortranOnly/CMakeLists.txt
index b5b5e56e7..ee47da455 100644
--- a/Tests/FortranOnly/CMakeLists.txt
+++ b/Tests/FortranOnly/CMakeLists.txt
@@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 2.8.12)
project(FortranOnly Fortran)
message("CTEST_FULL_OUTPUT ")
+if("${CMAKE_Fortran_COMPILER_ID};${CMAKE_Fortran_SIMULATE_ID}" MATCHES "^Intel(LLVM)?;MSVC$")
+ string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -Z7")
+ string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO " -Z7")
+endif()
+
# create a library with hello and world functions
add_library(FortranOnlylib hello.f world.f)
set_property(TARGET FortranOnlylib PROPERTY Fortran_FORMAT FIXED)
@@ -117,15 +122,9 @@ if(CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
target_compile_definitions(IntelIfDef PRIVATE SOME_DEF)
endif()
-# Skip these tests if compiler/version doesn't have preprocessing flags
-if((CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 4.4)
- OR (CMAKE_Fortran_COMPILER_ID STREQUAL "XL" AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 15.1.6))
- set(test_pp_flags 0)
-else()
- set(test_pp_flags 1)
-endif()
-
-if(test_pp_flags)
+# Skip these tests if compiler/version does enable and disable preprocessing
+if(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON AND
+ CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF)
# Test that we can always preprocess a target
add_executable(preprocess_target preprocess2.f)
set_property(TARGET preprocess_target PROPERTY Fortran_PREPROCESS ON)
@@ -145,17 +144,22 @@ set_property(SOURCE no_preprocess_source_lower.f PROPERTY Fortran_PREPROCESS OFF
# Test that we can explicitly not preprocess a target or source.
# This will not work on certain compilers due to either missing a
-# "don't preprocess" flag, or due to choice of file extension.
-if(test_pp_flags AND NOT CMAKE_Fortran_COMPILER_ID MATCHES "(Flang|NAG|PGI|NVHPC|SunPro|XL)")
+# "don't preprocess" flag, or due to the flags being ignored for
+# extensions like '.F' and '.fpp'.
+if(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF AND
+ NOT CMAKE_Fortran_COMPILER_ID MATCHES "(Flang|NAG|PGI|NVHPC|SunPro|XL)")
add_library(no_preprocess_target STATIC no_preprocess_target_upper.F)
target_compile_options(no_preprocess_target PRIVATE -DINTEGER=nonsense)
+
add_library(no_preprocess_source STATIC no_preprocess_source_upper.F)
target_compile_options(no_preprocess_source PRIVATE -DINTEGER=nonsense)
+
if(NOT CMAKE_Fortran_COMPILER_ID STREQUAL "Cray"
AND NOT "${CMAKE_Fortran_COMPILER_ID};${CMAKE_Fortran_SIMULATE_ID}" MATCHES "Intel(LLVM)?;MSVC")
target_sources(no_preprocess_target PRIVATE no_preprocess_target_fpp.fpp)
target_sources(no_preprocess_source PRIVATE no_preprocess_source_fpp.fpp)
endif()
+
set_property(TARGET no_preprocess_target PROPERTY Fortran_PREPROCESS OFF)
set_property(SOURCE no_preprocess_source_upper.F no_preprocess_source_fpp.fpp PROPERTY Fortran_PREPROCESS OFF)
endif()
diff --git a/Tests/Framework/CMakeLists.txt b/Tests/Framework/CMakeLists.txt
index aabf6b419..287be949d 100644
--- a/Tests/Framework/CMakeLists.txt
+++ b/Tests/Framework/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(Framework)
add_library(foo SHARED
@@ -83,7 +83,7 @@ if(NOT XCODE OR NOT XCODE_VERSION VERSION_LESS 5)
target_link_libraries(barStatic fooStatic)
endif()
-if(XCODE)
+if(MAKE_SUPPORTS_SPACES AND NOT CMAKE_GENERATOR STREQUAL "Watcom WMake")
add_library(space SHARED space.c)
set_target_properties(space PROPERTIES
FRAMEWORK TRUE
diff --git a/Tests/FunctionTest/CMakeLists.txt b/Tests/FunctionTest/CMakeLists.txt
index 68da972c6..64504470d 100644
--- a/Tests/FunctionTest/CMakeLists.txt
+++ b/Tests/FunctionTest/CMakeLists.txt
@@ -1,5 +1,5 @@
# a simple C only test case
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project (FunctionTest)
function(FAILED testname)
diff --git a/Tests/HIP/ArchitectureOff/CMakeLists.txt b/Tests/HIP/ArchitectureOff/CMakeLists.txt
new file mode 100644
index 000000000..bccb3b4f8
--- /dev/null
+++ b/Tests/HIP/ArchitectureOff/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.18)
+project(HIPArchitecture HIP)
+
+# Make sure CMake doesn't pass architectures if HIP_ARCHITECTURES is OFF.
+string(APPEND CMAKE_HIP_FLAGS " --offload-arch=gfx908")
+
+add_executable(HIPOnlyArchitectureOff main.hip)
+set_property(TARGET HIPOnlyArchitectureOff PROPERTY HIP_ARCHITECTURES OFF)
diff --git a/Tests/HIP/ArchitectureOff/main.hip b/Tests/HIP/ArchitectureOff/main.hip
new file mode 100644
index 000000000..9256318cc
--- /dev/null
+++ b/Tests/HIP/ArchitectureOff/main.hip
@@ -0,0 +1,9 @@
+#ifdef __HIP_DEVICE_COMPILE__
+# ifndef __gfx908__
+# error "Passed architecture gfx908, but got something else."
+# endif
+#endif
+
+int main()
+{
+}
diff --git a/Tests/HIP/CMakeLists.txt b/Tests/HIP/CMakeLists.txt
new file mode 100644
index 000000000..9499be8f6
--- /dev/null
+++ b/Tests/HIP/CMakeLists.txt
@@ -0,0 +1,15 @@
+macro (add_hip_test_macro name)
+ add_test_macro("${name}" ${ARGN})
+ set_property(TEST "${name}" APPEND
+ PROPERTY LABELS "HIP")
+endmacro ()
+
+add_hip_test_macro(HIP.ArchitectureOff HIPOnlyArchitectureOff)
+add_hip_test_macro(HIP.CompileFlags HIPOnlyCompileFlags)
+add_hip_test_macro(HIP.EnableStandard HIPEnableStandard)
+add_hip_test_macro(HIP.InferHipLang1 HIPInferHipLang1)
+add_hip_test_macro(HIP.InferHipLang2 HIPInferHipLang2)
+add_hip_test_macro(HIP.MathFunctions HIPOnlyMathFunctions)
+add_hip_test_macro(HIP.MixedLanguage HIPMixedLanguage)
+add_hip_test_macro(HIP.TryCompile HIPOnlyTryCompile)
+add_hip_test_macro(HIP.WithDefs HIPOnlyWithDefs)
diff --git a/Tests/HIP/CompileFlags/CMakeLists.txt b/Tests/HIP/CompileFlags/CMakeLists.txt
new file mode 100644
index 000000000..c80831387
--- /dev/null
+++ b/Tests/HIP/CompileFlags/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.18)
+project(CompileFlags HIP)
+
+add_executable(HIPOnlyCompileFlags main.hip)
+
+set_property(TARGET HIPOnlyCompileFlags PROPERTY HIP_ARCHITECTURES gfx803)
+
+target_compile_options(HIPOnlyCompileFlags PRIVATE -DALWAYS_DEFINE)
diff --git a/Tests/HIP/CompileFlags/main.hip b/Tests/HIP/CompileFlags/main.hip
new file mode 100644
index 000000000..3259f1d31
--- /dev/null
+++ b/Tests/HIP/CompileFlags/main.hip
@@ -0,0 +1,13 @@
+#ifdef __HIP_DEVICE_COMPILE__
+# ifndef __gfx803__
+# error "Passed architecture gfx803, but got something else."
+# endif
+#endif
+
+#ifndef ALWAYS_DEFINE
+# error "ALWAYS_DEFINE not defined!"
+#endif
+
+int main()
+{
+}
diff --git a/Tests/HIP/EnableStandard/CMakeLists.txt b/Tests/HIP/EnableStandard/CMakeLists.txt
new file mode 100644
index 000000000..670172467
--- /dev/null
+++ b/Tests/HIP/EnableStandard/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.18)
+project (EnableStandard HIP)
+
+set(CMAKE_CXX_COMPILER ${CMAKE_HIP_COMPILER})
+enable_language(CXX)
+
+#Goal for this example:
+#build hip sources that require C++11 to be enabled.
+
+add_library(HIPStatic11 STATIC static.cxx)
+set_source_files_properties(static.cxx PROPERTIES LANGUAGE HIP)
+
+add_library(HIPDynamic11 SHARED shared.hip)
+
+add_executable(HIPEnableStandard main.hip)
+target_link_libraries(HIPEnableStandard PRIVATE HIPStatic11 HIPDynamic11)
+
+target_compile_features(HIPDynamic11 PRIVATE cxx_std_11)
+set_target_properties(HIPStatic11 PROPERTIES HIP_STANDARD 11)
+set_target_properties(HIPStatic11 PROPERTIES HIP_STANDARD_REQUIRED TRUE)
diff --git a/Tests/HIP/EnableStandard/main.hip b/Tests/HIP/EnableStandard/main.hip
new file mode 100644
index 000000000..7dc32e806
--- /dev/null
+++ b/Tests/HIP/EnableStandard/main.hip
@@ -0,0 +1,23 @@
+
+#include <iostream>
+
+#ifdef _WIN32
+# define IMPORT __declspec(dllimport)
+#else
+# define IMPORT
+#endif
+
+int static_hip11_func(int);
+IMPORT int shared_hip11_func(int);
+
+void test_functions()
+{
+ static_hip11_func(int(42));
+ shared_hip11_func(int(42));
+}
+
+int main(int argc, char** argv)
+{
+ test_functions();
+ return 0;
+}
diff --git a/Tests/HIP/EnableStandard/shared.hip b/Tests/HIP/EnableStandard/shared.hip
new file mode 100644
index 000000000..204225863
--- /dev/null
+++ b/Tests/HIP/EnableStandard/shared.hip
@@ -0,0 +1,15 @@
+
+#include <type_traits>
+
+#ifdef _WIN32
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT
+#endif
+
+using tt = std::true_type;
+using ft = std::false_type;
+EXPORT int __host__ shared_hip11_func(int x)
+{
+ return x * x + std::integral_constant<int, 17>::value;
+}
diff --git a/Tests/HIP/EnableStandard/static.cxx b/Tests/HIP/EnableStandard/static.cxx
new file mode 100644
index 000000000..29558945e
--- /dev/null
+++ b/Tests/HIP/EnableStandard/static.cxx
@@ -0,0 +1,9 @@
+
+#include <type_traits>
+
+using tt = std::true_type;
+using ft = std::false_type;
+int __host__ static_hip11_func(int x)
+{
+ return x * x + std::integral_constant<int, 17>::value;
+}
diff --git a/Tests/HIP/InferHipLang1/CMakeLists.txt b/Tests/HIP/InferHipLang1/CMakeLists.txt
new file mode 100644
index 000000000..63d77fdaa
--- /dev/null
+++ b/Tests/HIP/InferHipLang1/CMakeLists.txt
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 3.18)
+project(InferHipLang C CXX HIP)
+
+#Goal for this example:
+#make sure that we understand that HIP is the correct link language
+add_library(InterfaceWithHIP INTERFACE)
+target_sources(InterfaceWithHIP INTERFACE interface.hip main.cxx)
+target_compile_features(InterfaceWithHIP INTERFACE hip_std_14)
+target_compile_features(InterfaceWithHIP INTERFACE cxx_std_11)
+
+add_executable(HIPInferHipLang1 )
+target_link_libraries(HIPInferHipLang1 PRIVATE InterfaceWithHIP)
diff --git a/Tests/HIP/InferHipLang1/interface.hip b/Tests/HIP/InferHipLang1/interface.hip
new file mode 100644
index 000000000..6ac8641cc
--- /dev/null
+++ b/Tests/HIP/InferHipLang1/interface.hip
@@ -0,0 +1,19 @@
+#include <system_error>
+#include <type_traits>
+#include <hip/hip_runtime_api.h>
+
+static __global__ void fake_hip_kernel()
+{
+}
+
+
+int __host__ interface_hip_func(int x)
+{
+
+ fake_hip_kernel<<<1, 1>>>();
+ bool valid = (hipSuccess == hipGetLastError());
+ if (!valid) {
+ throw std::system_error(ENODEV, std::generic_category(), "no hip device");
+ }
+ return x * x + std::integral_constant<int, 17>::value;
+}
diff --git a/Tests/HIP/InferHipLang1/main.cxx b/Tests/HIP/InferHipLang1/main.cxx
new file mode 100644
index 000000000..987b6c651
--- /dev/null
+++ b/Tests/HIP/InferHipLang1/main.cxx
@@ -0,0 +1,19 @@
+
+#include <iostream>
+
+#ifdef __HIP_PLATFORM_HCC__
+# error "__HIP_PLATFORM_HCC__ propagated to C++ compilation!"
+#endif
+
+#ifdef __HIP_ROCclr__
+# error "__HIP_ROCclr__ propagated to C++ compilation!"
+#endif
+
+int interface_hip_func(int);
+
+int main(int argc, char** argv)
+{
+ interface_hip_func(int(42));
+
+ return 0;
+}
diff --git a/Tests/HIP/InferHipLang2/CMakeLists.txt b/Tests/HIP/InferHipLang2/CMakeLists.txt
new file mode 100644
index 000000000..0e69de38f
--- /dev/null
+++ b/Tests/HIP/InferHipLang2/CMakeLists.txt
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 3.18)
+project(InferHipLang C CXX HIP)
+
+#Goal for this example:
+#make sure that we understand that HIP is the correct link language
+add_library(InterfaceWithHIP OBJECT)
+target_sources(InterfaceWithHIP PRIVATE interface.hip main.cxx)
+target_compile_features(InterfaceWithHIP INTERFACE hip_std_14)
+target_compile_features(InterfaceWithHIP INTERFACE cxx_std_11)
+
+add_executable(HIPInferHipLang2 )
+target_link_libraries(HIPInferHipLang2 PRIVATE InterfaceWithHIP)
diff --git a/Tests/HIP/InferHipLang2/interface.hip b/Tests/HIP/InferHipLang2/interface.hip
new file mode 100644
index 000000000..6ac8641cc
--- /dev/null
+++ b/Tests/HIP/InferHipLang2/interface.hip
@@ -0,0 +1,19 @@
+#include <system_error>
+#include <type_traits>
+#include <hip/hip_runtime_api.h>
+
+static __global__ void fake_hip_kernel()
+{
+}
+
+
+int __host__ interface_hip_func(int x)
+{
+
+ fake_hip_kernel<<<1, 1>>>();
+ bool valid = (hipSuccess == hipGetLastError());
+ if (!valid) {
+ throw std::system_error(ENODEV, std::generic_category(), "no hip device");
+ }
+ return x * x + std::integral_constant<int, 17>::value;
+}
diff --git a/Tests/HIP/InferHipLang2/main.cxx b/Tests/HIP/InferHipLang2/main.cxx
new file mode 100644
index 000000000..987b6c651
--- /dev/null
+++ b/Tests/HIP/InferHipLang2/main.cxx
@@ -0,0 +1,19 @@
+
+#include <iostream>
+
+#ifdef __HIP_PLATFORM_HCC__
+# error "__HIP_PLATFORM_HCC__ propagated to C++ compilation!"
+#endif
+
+#ifdef __HIP_ROCclr__
+# error "__HIP_ROCclr__ propagated to C++ compilation!"
+#endif
+
+int interface_hip_func(int);
+
+int main(int argc, char** argv)
+{
+ interface_hip_func(int(42));
+
+ return 0;
+}
diff --git a/Tests/HIP/MathFunctions/CMakeLists.txt b/Tests/HIP/MathFunctions/CMakeLists.txt
new file mode 100644
index 000000000..81e3ddb26
--- /dev/null
+++ b/Tests/HIP/MathFunctions/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.18)
+project(MathFunctions HIP)
+
+# This test covers these major HIP language/runtime requirements:
+#
+# 1. This makes sure CMake properly specifies the internal clang header dirs
+# that hold headers needed for overloads of device side functions
+#
+# 2. This makes sure that all HIP include directories are properly marked as
+# system includes so we don't get the following warnings:
+# replacement function 'operator delete' cannot be declared 'inline'#
+#
+# 3. This makes sure CMake properly links to all the built-in libraries
+# that hip needs that inject support for __half support
+#
+add_executable(HIPOnlyMathFunctions main.hip)
+target_compile_options(HIPOnlyMathFunctions PRIVATE -Werror)
+target_compile_features(HIPOnlyMathFunctions PRIVATE hip_std_14)
diff --git a/Tests/HIP/MathFunctions/main.hip b/Tests/HIP/MathFunctions/main.hip
new file mode 100644
index 000000000..8a6e77f5d
--- /dev/null
+++ b/Tests/HIP/MathFunctions/main.hip
@@ -0,0 +1,40 @@
+
+#include <stdexcept>
+#include <cmath>
+#include <math.h>
+#include <memory>
+
+#include <hip/hip_runtime.h>
+#include <hip/hip_fp16.h>
+
+namespace {
+template<class T, class F>
+__global__ void global_entry_point(F f, T *out) {
+ *out = f();
+}
+
+template <class T, class F>
+bool verify(F f, T expected)
+{
+ std::unique_ptr<T> cpu_T(new T);
+ T* gpu_T = nullptr;
+ hipMalloc((void**)&gpu_T, sizeof(T));
+ hipLaunchKernelGGL(global_entry_point, 1, 1, 0, 0, f, gpu_T);
+ hipMemcpy(cpu_T.get(), gpu_T, sizeof(T), hipMemcpyDeviceToHost);
+ hipFree(gpu_T);
+ return (*cpu_T == expected);
+}
+}
+
+int main(int argc, char** argv)
+{
+ bool valid = verify([]__device__(){ return std::round(1.4f); }, 1.0f);
+ valid &= verify([]__device__(){ return max<_Float16>(1.0f, 2.0f); }, 2.0f);
+ valid &= verify([]__device__(){ return min<_Float16>(1.0f, 2.0f); }, 1.0f);
+
+ if (valid) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
diff --git a/Tests/HIP/MixedLanguage/CMakeLists.txt b/Tests/HIP/MixedLanguage/CMakeLists.txt
new file mode 100644
index 000000000..4f6dd3b0f
--- /dev/null
+++ b/Tests/HIP/MixedLanguage/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.18)
+project (MixedLanguage C CXX HIP)
+
+set(CMAKE_HIP_STANDARD 14)
+set(CMAKE_CXX_STANDARD 14)
+
+#Goal for this example:
+#make sure that we can build multiple languages into targets
+#and have the link language always be HIP
+add_library(MixedSharedLib SHARED shared.c)
+add_library(MixedObjectLib OBJECT shared.cxx shared.hip)
+set_target_properties(MixedObjectLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_link_libraries(MixedSharedLib PRIVATE MixedObjectLib)
+
+add_library(MixedStaticLib STATIC static.c static.cxx static.hip)
+set_target_properties(MixedStaticLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
+
+add_executable(HIPMixedLanguage main.cxx)
+target_link_libraries(HIPMixedLanguage PRIVATE MixedStaticLib MixedSharedLib)
diff --git a/Tests/HIP/MixedLanguage/main.cxx b/Tests/HIP/MixedLanguage/main.cxx
new file mode 100644
index 000000000..003d18ac4
--- /dev/null
+++ b/Tests/HIP/MixedLanguage/main.cxx
@@ -0,0 +1,40 @@
+
+#include <iostream>
+
+#ifdef __HIP_PLATFORM_HCC__
+# error "__HIP_PLATFORM_HCC__ propagated to C++ compilation!"
+#endif
+
+#ifdef __HIP_ROCclr__
+# error "__HIP_ROCclr__ propagated to C++ compilation!"
+#endif
+
+#ifdef _WIN32
+# define IMPORT __declspec(dllimport)
+#else
+# define IMPORT
+#endif
+
+extern "C" {
+IMPORT int shared_c_func(int);
+int static_c_func(int);
+}
+
+IMPORT int shared_cxx_func(int);
+IMPORT int shared_hip_func(int);
+
+int static_cxx_func(int);
+int static_hip_func(int);
+
+int main(int argc, char** argv)
+{
+ static_c_func(int(42));
+ static_cxx_func(int(42));
+ static_hip_func(int(42));
+
+ shared_c_func(int(42));
+ shared_cxx_func(int(42));
+ shared_hip_func(int(42));
+
+ return 0;
+}
diff --git a/Tests/HIP/MixedLanguage/shared.c b/Tests/HIP/MixedLanguage/shared.c
new file mode 100644
index 000000000..347fba925
--- /dev/null
+++ b/Tests/HIP/MixedLanguage/shared.c
@@ -0,0 +1,12 @@
+
+
+#ifdef _WIN32
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT
+#endif
+
+EXPORT int shared_c_func(int x)
+{
+ return -x;
+}
diff --git a/Tests/HIP/MixedLanguage/shared.cxx b/Tests/HIP/MixedLanguage/shared.cxx
new file mode 100644
index 000000000..8e6c1d35f
--- /dev/null
+++ b/Tests/HIP/MixedLanguage/shared.cxx
@@ -0,0 +1,21 @@
+
+#include <type_traits>
+
+#ifdef __HIP_PLATFORM_HCC__
+# error "__HIP_PLATFORM_HCC__ propagated to C++ compilation!"
+#endif
+
+#ifdef __HIP_ROCclr__
+# error "__HIP_ROCclr__ propagated to C++ compilation!"
+#endif
+
+#ifdef _WIN32
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT
+#endif
+
+EXPORT int shared_cxx_func(int x)
+{
+ return x * x + std::integral_constant<int, 14>::value;
+}
diff --git a/Tests/HIP/MixedLanguage/shared.hip b/Tests/HIP/MixedLanguage/shared.hip
new file mode 100644
index 000000000..e6fea9fe2
--- /dev/null
+++ b/Tests/HIP/MixedLanguage/shared.hip
@@ -0,0 +1,26 @@
+#include <system_error>
+#include <type_traits>
+#include <hip/hip_runtime_api.h>
+
+#ifdef _WIN32
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT
+#endif
+
+
+static __global__ void fake_hip_kernel()
+{
+}
+
+
+int __host__ shared_hip_func(int x)
+{
+
+ fake_hip_kernel<<<1, 1>>>();
+ bool valid = (hipSuccess == hipGetLastError());
+ if (!valid) {
+ throw std::system_error(ENODEV, std::generic_category(), "no hip device");
+ }
+ return x * x + std::integral_constant<int, 17>::value;
+}
diff --git a/Tests/HIP/MixedLanguage/static.c b/Tests/HIP/MixedLanguage/static.c
new file mode 100644
index 000000000..06c33b4cc
--- /dev/null
+++ b/Tests/HIP/MixedLanguage/static.c
@@ -0,0 +1,6 @@
+
+
+int static_c_func(int x)
+{
+ return -x;
+}
diff --git a/Tests/HIP/MixedLanguage/static.cxx b/Tests/HIP/MixedLanguage/static.cxx
new file mode 100644
index 000000000..2c14fb101
--- /dev/null
+++ b/Tests/HIP/MixedLanguage/static.cxx
@@ -0,0 +1,7 @@
+
+#include <type_traits>
+
+int static_cxx_func(int x)
+{
+ return x * x + std::integral_constant<int, 14>::value;
+}
diff --git a/Tests/HIP/MixedLanguage/static.hip b/Tests/HIP/MixedLanguage/static.hip
new file mode 100644
index 000000000..359b9facd
--- /dev/null
+++ b/Tests/HIP/MixedLanguage/static.hip
@@ -0,0 +1,21 @@
+
+#include <type_traits>
+#include <system_error>
+#include <hip/hip_runtime_api.h>
+
+
+static __global__ void fake_hip_kernel()
+{
+}
+
+
+int __host__ static_hip_func(int x)
+{
+
+ fake_hip_kernel<<<1, 1>>>();
+ bool valid = (hipSuccess == hipGetLastError());
+ if (!valid) {
+ throw std::system_error(ENODEV, std::generic_category(), "no hip device");
+ }
+ return x * x + std::integral_constant<int, 17>::value;
+}
diff --git a/Tests/HIP/TryCompile/CMakeLists.txt b/Tests/HIP/TryCompile/CMakeLists.txt
new file mode 100644
index 000000000..92a834c61
--- /dev/null
+++ b/Tests/HIP/TryCompile/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.18)
+project (TryCompile HIP)
+
+#Goal for this example:
+# Verify try_compile with HIP language works
+set(CMAKE_HIP_STANDARD 14)
+set(CMAKE_HIP_ARCHITECTURES gfx803 gfx900)
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+try_compile(result "${CMAKE_CURRENT_BINARY_DIR}"
+ SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/device_function.hip"
+ COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/device_function.o")
+
+add_executable(HIPOnlyTryCompile main.hip)
+target_link_libraries(HIPOnlyTryCompile "${CMAKE_CURRENT_BINARY_DIR}/device_function.o")
diff --git a/Tests/HIP/TryCompile/device_function.hip b/Tests/HIP/TryCompile/device_function.hip
new file mode 100644
index 000000000..7c1205e6d
--- /dev/null
+++ b/Tests/HIP/TryCompile/device_function.hip
@@ -0,0 +1,17 @@
+#include <system_error>
+#include <hip/hip_runtime_api.h>
+
+static __global__ void fake_hip_kernel()
+{
+}
+
+int __host__ try_compile_hip_func(int x)
+{
+
+ fake_hip_kernel<<<1, 1>>>();
+ bool valid = (hipSuccess == hipGetLastError());
+ if (!valid) {
+ throw std::system_error(ENODEV, std::generic_category(), "no hip device");
+ }
+ return x * x;
+}
diff --git a/Tests/HIP/TryCompile/main.hip b/Tests/HIP/TryCompile/main.hip
new file mode 100644
index 000000000..091dca3bc
--- /dev/null
+++ b/Tests/HIP/TryCompile/main.hip
@@ -0,0 +1,8 @@
+int __host__ try_compile_hip_func(int x);
+
+int main(int argc, char** argv)
+{
+ try_compile_hip_func(int(42));
+
+ return 0;
+}
diff --git a/Tests/HIP/WithDefs/CMakeLists.txt b/Tests/HIP/WithDefs/CMakeLists.txt
new file mode 100644
index 000000000..e2db1820a
--- /dev/null
+++ b/Tests/HIP/WithDefs/CMakeLists.txt
@@ -0,0 +1,37 @@
+
+cmake_minimum_required(VERSION 3.18)
+project (WithDefs HIP)
+
+set(CMAKE_HIP_ARCHITECTURES OFF)
+set(release_compile_defs DEFREL)
+
+#Goal for this example:
+#build a executable that needs to be passed a complex define through add_definitions
+#this verifies we can pass C++ style attributes to hipcc
+add_definitions("-DPACKED_DEFINE=[[gnu::packed]]")
+
+add_executable(HIPOnlyWithDefs main.hip.cpp)
+set_source_files_properties(main.hip.cpp PROPERTIES LANGUAGE HIP)
+
+target_compile_features(HIPOnlyWithDefs PRIVATE hip_std_17)
+
+target_compile_options(HIPOnlyWithDefs
+ PRIVATE
+ --offload-arch=gfx900
+ -DFLAG_COMPILE_LANG_$<COMPILE_LANGUAGE>
+ $<$<HIP_COMPILER_ID:ROCMClang>:-DFLAG_LANG_IS_HIP=$<COMPILE_LANGUAGE:HIP>> # Host-only defines are possible only on NVCC.
+ )
+
+target_compile_definitions(HIPOnlyWithDefs
+ PRIVATE
+ $<$<CONFIG:RELEASE>:$<BUILD_INTERFACE:${release_compile_defs}>>
+ -DDEF_COMPILE_LANG_$<COMPILE_LANGUAGE>
+ -DDEF_LANG_IS_HIP=$<COMPILE_LANGUAGE:HIP>
+ -DDEF_HIP_COMPILER=$<HIP_COMPILER_ID>
+ -DDEF_HIP_COMPILER_VERSION=$<HIP_COMPILER_VERSION>
+ )
+
+target_include_directories(HIPOnlyWithDefs
+ PRIVATE
+ $<$<COMPILE_LANGUAGE:HIP>:${CMAKE_CURRENT_SOURCE_DIR}/inc_hip>
+)
diff --git a/Tests/HIP/WithDefs/inc_hip/inc_hip.h b/Tests/HIP/WithDefs/inc_hip/inc_hip.h
new file mode 100644
index 000000000..fe2698a02
--- /dev/null
+++ b/Tests/HIP/WithDefs/inc_hip/inc_hip.h
@@ -0,0 +1 @@
+#define INC_HIP
diff --git a/Tests/HIP/WithDefs/main.hip.cpp b/Tests/HIP/WithDefs/main.hip.cpp
new file mode 100644
index 000000000..a8f2d185b
--- /dev/null
+++ b/Tests/HIP/WithDefs/main.hip.cpp
@@ -0,0 +1,89 @@
+#include <iostream>
+
+#include <hip/hip_runtime_api.h>
+#include <inc_hip.h>
+#ifndef INC_HIP
+# error "INC_HIP not defined!"
+#endif
+
+#ifndef PACKED_DEFINE
+# error "PACKED_DEFINE not defined!"
+#endif
+
+#ifndef FLAG_COMPILE_LANG_HIP
+# error "FLAG_COMPILE_LANG_HIP not defined!"
+#endif
+
+#ifndef FLAG_LANG_IS_HIP
+# error "FLAG_LANG_IS_HIP not defined!"
+#endif
+
+#if !FLAG_LANG_IS_HIP
+# error "Expected FLAG_LANG_IS_HIP"
+#endif
+
+#ifndef DEF_COMPILE_LANG_HIP
+# error "DEF_COMPILE_LANG_HIP not defined!"
+#endif
+
+#ifndef DEF_LANG_IS_HIP
+# error "DEF_LANG_IS_HIP not defined!"
+#endif
+
+#if !DEF_LANG_IS_HIP
+# error "Expected DEF_LANG_IS_HIP"
+#endif
+
+#ifndef DEF_HIP_COMPILER
+# error "DEF_HIP_COMPILER not defined!"
+#endif
+
+#ifndef DEF_HIP_COMPILER_VERSION
+# error "DEF_HIP_COMPILER_VERSION not defined!"
+#endif
+
+static __global__ void DetermineIfValidHIPDevice()
+{
+}
+
+#ifdef _MSC_VER
+# pragma pack(push, 1)
+# undef PACKED_DEFINE
+# define PACKED_DEFINE
+#endif
+struct PACKED_DEFINE result_type
+{
+ bool valid;
+ int value;
+#if defined(NDEBUG) && !defined(DEFREL)
+# error missing DEFREL flag
+#endif
+};
+#ifdef _MSC_VER
+# pragma pack(pop)
+#endif
+
+result_type can_launch_kernel()
+{
+ result_type r;
+ DetermineIfValidHIPDevice<<<1, 1>>>();
+ r.valid = (hipSuccess == hipGetLastError());
+ if (r.valid) {
+ r.value = 1;
+ } else {
+ r.value = -1;
+ }
+ return r;
+}
+
+int main(int argc, char** argv)
+{
+ hipError_t err;
+ int nDevices = 0;
+ err = hipGetDeviceCount(&nDevices);
+ if (err != hipSuccess) {
+ std::cerr << hipGetErrorString(err) << std::endl;
+ return 1;
+ }
+ return 0;
+}
diff --git a/Tests/JCTest/CMakeLists.txt b/Tests/JCTest/CMakeLists.txt
index 31dcc3abf..b1206408d 100644
--- a/Tests/JCTest/CMakeLists.txt
+++ b/Tests/JCTest/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.8.12)
project(TestTime)
enable_testing()
add_executable(TestTime TestTime.cxx)
diff --git a/Tests/Java/CMakeLists.txt b/Tests/Java/CMakeLists.txt
index aea4282e7..1d8d7ac67 100644
--- a/Tests/Java/CMakeLists.txt
+++ b/Tests/Java/CMakeLists.txt
@@ -1,6 +1,6 @@
project(hello Java)
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
set(CMAKE_VERBOSE_MAKEFILE 1)
include(CTest)
@@ -17,9 +17,16 @@ add_jar(hello2 @${CMAKE_CURRENT_BINARY_DIR}/java_fileslist)
# use listing file to specify sources and specify output directory (issue #17316)
add_jar(hello3 @${CMAKE_CURRENT_BINARY_DIR}/java_fileslist OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/hello3")
+add_jar(ResourceNS
+ SOURCES ResourceNS.java
+ RESOURCES NAMESPACE ns/ns1 HelloWorld.txt
+ NAMESPACE ns/ns2 HelloWorld.txt) # add a second namespace
+
add_test (NAME Java.Jar
COMMAND "${Java_JAVA_EXECUTABLE}" -classpath hello.jar HelloWorld)
add_test (NAME Java.JarSourceList
COMMAND "${Java_JAVA_EXECUTABLE}" -classpath hello2.jar HelloWorld)
add_test (NAME Java.JarSourceListAndOutput
COMMAND "${Java_JAVA_EXECUTABLE}" -classpath "${CMAKE_CURRENT_BINARY_DIR}/hello3/hello3.jar" HelloWorld)
+add_test (NAME Java.JarResourceNS
+ COMMAND "${Java_JAVA_EXECUTABLE}" -classpath ResourceNS.jar ResourceNS)
diff --git a/Tests/Java/HelloWorld.txt b/Tests/Java/HelloWorld.txt
new file mode 100644
index 000000000..d7407a1fc
--- /dev/null
+++ b/Tests/Java/HelloWorld.txt
@@ -0,0 +1 @@
+Hello World !
diff --git a/Tests/Java/ResourceNS.java b/Tests/Java/ResourceNS.java
new file mode 100644
index 000000000..7289e6ea3
--- /dev/null
+++ b/Tests/Java/ResourceNS.java
@@ -0,0 +1,48 @@
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+class ResourceNS
+{
+ public static void main(String args[])
+ {
+ ResourceNS res = new ResourceNS();
+ res.displayResourceText();
+ }
+
+ public void displayResourceText()
+ {
+ /*
+ * Since Java SE 9, invoking getResourceXXX on a class in a named
+ * module will only locate the resource in that module, it will
+ * not search the class path as it did in previous release. So when
+ * you use Class.getClassLoader().getResource() it will attempt to
+ * locate the resource in the module containing the ClassLoader,
+ * possibly something like:
+ * jdk.internal.loader.ClassLoaders.AppClassLoader
+ * which is probably not the module that your resource is in, so it
+ * returns null.
+ *
+ * You have to make java 9+ search for the file in your module.
+ * Do that by changing Class to any class defined in your module in
+ * order to make java use the proper class loader.
+ */
+
+ // Namespaces are relative, use leading '/' for full namespace
+ InputStream is =
+ ResourceNS.class.getResourceAsStream("/ns/ns1/HelloWorld.txt");
+ // C++: cout << is.readline(); // oh, well !
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader reader = new BufferedReader(isr);
+ String out = "";
+ try{
+ out = reader.readLine();
+ } catch(IOException e) {
+ e.printStackTrace();
+ System.out.println(e);
+ }
+
+ System.out.println(out);
+ }
+}
diff --git a/Tests/JavaJavah/CMakeLists.txt b/Tests/JavaJavah/CMakeLists.txt
index 77c292a32..b56cc216e 100644
--- a/Tests/JavaJavah/CMakeLists.txt
+++ b/Tests/JavaJavah/CMakeLists.txt
@@ -1,6 +1,6 @@
project(helloJavah Java CXX)
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
set(CMAKE_VERBOSE_MAKEFILE 1)
include(CTest)
diff --git a/Tests/JavaNativeHeaders/CMakeLists.txt b/Tests/JavaNativeHeaders/CMakeLists.txt
index f3cc89d68..2471e013f 100644
--- a/Tests/JavaNativeHeaders/CMakeLists.txt
+++ b/Tests/JavaNativeHeaders/CMakeLists.txt
@@ -1,6 +1,6 @@
project(helloJavaNativeHeaders Java CXX)
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
set(CMAKE_VERBOSE_MAKEFILE 1)
include (CTest)
diff --git a/Tests/LibName/CMakeLists.txt b/Tests/LibName/CMakeLists.txt
index 3ac125fb9..b8f089092 100644
--- a/Tests/LibName/CMakeLists.txt
+++ b/Tests/LibName/CMakeLists.txt
@@ -24,3 +24,11 @@ set_target_properties(verFoo PROPERTIES VERSION 3.1.4 SOVERSION 3)
add_executable(verFoobar foobar.c)
target_link_libraries(verFoobar verFoo)
+
+if(MAKE_SUPPORTS_SPACES AND NOT CMAKE_GENERATOR STREQUAL "Watcom WMake")
+ # check with lib version and space
+ add_library(ver_space SHARED ver_space.c)
+ set_target_properties(ver_space PROPERTIES VERSION 3.1.4 SOVERSION 3 OUTPUT_NAME "ver space")
+ add_executable(use_ver_space use_ver_space.c)
+ target_link_libraries(use_ver_space ver_space)
+endif()
diff --git a/Tests/LibName/use_ver_space.c b/Tests/LibName/use_ver_space.c
new file mode 100644
index 000000000..a6a733df5
--- /dev/null
+++ b/Tests/LibName/use_ver_space.c
@@ -0,0 +1,9 @@
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ int ver_space(void);
+
+int main(void)
+{
+ return ver_space();
+}
diff --git a/Tests/LibName/ver_space.c b/Tests/LibName/ver_space.c
new file mode 100644
index 000000000..669a3b528
--- /dev/null
+++ b/Tests/LibName/ver_space.c
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int ver_space(void)
+{
+ return 0;
+}
diff --git a/Tests/LoadCommand/CMakeCommands/CMakeLists.txt b/Tests/LoadCommand/CMakeCommands/CMakeLists.txt
index 99b1aba82..cafa99b90 100644
--- a/Tests/LoadCommand/CMakeCommands/CMakeLists.txt
+++ b/Tests/LoadCommand/CMakeCommands/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CMAKE_LOADED_COMMANDS)
if (MUDSLIDE_TYPE MATCHES MUCHO)
diff --git a/Tests/LoadCommand/CMakeLists.txt b/Tests/LoadCommand/CMakeLists.txt
index cfaebade4..e1c4998c6 100644
--- a/Tests/LoadCommand/CMakeLists.txt
+++ b/Tests/LoadCommand/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(LoadCommand)
# set a definition
diff --git a/Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt b/Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt
index 5ee2ed0f1..dc029a4f7 100644
--- a/Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt
+++ b/Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(CMAKE_LOADED_COMMANDS)
if (MUDSLIDE_TYPE MATCHES MUCHO)
diff --git a/Tests/LoadCommandOneConfig/CMakeLists.txt b/Tests/LoadCommandOneConfig/CMakeLists.txt
index 65de04230..fef4bb777 100644
--- a/Tests/LoadCommandOneConfig/CMakeLists.txt
+++ b/Tests/LoadCommandOneConfig/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(LoadCommand)
# set a definition
diff --git a/Tests/MakeClean/CMakeLists.txt b/Tests/MakeClean/CMakeLists.txt
index fbd499534..809d65bcc 100644
--- a/Tests/MakeClean/CMakeLists.txt
+++ b/Tests/MakeClean/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(MakeClean)
# Build the to-clean project.
diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
index 0cf74bf08..e4067580a 100644
--- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
+++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
@@ -52,7 +52,7 @@ endmacro()
# detailed features tables, not just meta-features
if (CMAKE_C_COMPILE_FEATURES)
- if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$")
+ if (NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu|FujitsuClang)$")
set(C_expected_features ${CMAKE_C_COMPILE_FEATURES})
list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]")
endif()
@@ -95,7 +95,7 @@ if (C_expected_features)
endif()
if (CMAKE_CXX_COMPILE_FEATURES)
- if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$")
+ if (NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu|FujitsuClang)$")
set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES})
list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]")
endif()
diff --git a/Tests/ModuleDefinition/CMakeLists.txt b/Tests/ModuleDefinition/CMakeLists.txt
index e49ebea52..567fb4b9f 100644
--- a/Tests/ModuleDefinition/CMakeLists.txt
+++ b/Tests/ModuleDefinition/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.8.12)
project(ModuleDefinition C)
# Test .def file source recognition for DLLs.
diff --git a/Tests/NewlineArgs/CMakeLists.txt b/Tests/NewlineArgs/CMakeLists.txt
index 755160102..3e4b436f5 100644
--- a/Tests/NewlineArgs/CMakeLists.txt
+++ b/Tests/NewlineArgs/CMakeLists.txt
@@ -1,5 +1,5 @@
# a simple CXX only test case
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project (NewlineArgs CXX)
add_definitions("-DTEST_FLAG_1
diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt
index 74f34e4d0..06167a83f 100644
--- a/Tests/ObjectLibrary/CMakeLists.txt
+++ b/Tests/ObjectLibrary/CMakeLists.txt
@@ -74,4 +74,6 @@ target_link_libraries(UseABstaticObjs ABstatic)
add_subdirectory(ExportLanguages)
+add_subdirectory(LinkObjects)
+
add_subdirectory(Transitive)
diff --git a/Tests/ObjectLibrary/LinkObjects/CMakeLists.txt b/Tests/ObjectLibrary/LinkObjects/CMakeLists.txt
new file mode 100644
index 000000000..899be4518
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/CMakeLists.txt
@@ -0,0 +1,45 @@
+add_executable(LinkObjects main.c)
+
+# Link TARGET_OBJECTS through LINK_LIBRARIES.
+add_library(LinkObjectsAObj OBJECT a_obj.c)
+add_library(LinkObjectsADep STATIC a_dep.c)
+target_compile_definitions(LinkObjectsAObj PUBLIC OBJA)
+target_link_libraries(LinkObjects PRIVATE LinkObjectsADep $<TARGET_OBJECTS:LinkObjectsAObj>)
+
+# Link TARGET_OBJECTS through INTERFACE_LINK_LIBRARIES with usage requirements.
+add_library(LinkObjectsB INTERFACE)
+add_library(LinkObjectsBObj OBJECT b_obj.c)
+add_library(LinkObjectsBDep STATIC b_dep.c)
+target_compile_definitions(LinkObjectsBObj PUBLIC OBJB)
+target_link_libraries(LinkObjectsB INTERFACE LinkObjectsBObj $<TARGET_OBJECTS:LinkObjectsBObj>)
+target_link_libraries(LinkObjectsBObj PRIVATE LinkObjectsBDep)
+target_link_libraries(LinkObjects PRIVATE LinkObjectsB)
+
+# Link TARGET_OBJECTS through INTERFACE_LINK_LIBRARIES without usage requirements.
+add_library(LinkObjectsC INTERFACE)
+add_library(LinkObjectsCObj OBJECT c_obj.c)
+add_library(LinkObjectsCDep STATIC c_dep.c)
+target_compile_definitions(LinkObjectsCObj PUBLIC OBJC)
+target_link_libraries(LinkObjectsC INTERFACE LinkObjectsCDep $<TARGET_OBJECTS:LinkObjectsCObj>)
+target_link_libraries(LinkObjectsCObj PRIVATE LinkObjectsCDep)
+target_link_libraries(LinkObjects PRIVATE LinkObjectsC)
+
+# Link TARGET_OBJECTS through both LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES, deduplicated.
+add_library(LinkObjectsD INTERFACE)
+add_library(LinkObjectsDObj OBJECT d_obj.c)
+add_library(LinkObjectsDDep STATIC d_dep.c)
+target_compile_definitions(LinkObjectsDObj PUBLIC OBJD)
+target_link_libraries(LinkObjectsD INTERFACE LinkObjectsDObj $<TARGET_OBJECTS:LinkObjectsDObj>)
+target_link_libraries(LinkObjectsDObj PRIVATE LinkObjectsDDep)
+target_link_libraries(LinkObjects PRIVATE $<TARGET_OBJECTS:LinkObjectsDObj> LinkObjectsD)
+
+# Link TARGET_OBJECTS through STATIC library private dependency.
+add_library(LinkObjectsE INTERFACE)
+add_library(LinkObjectsEObj OBJECT e_obj.c)
+add_library(LinkObjectsEDep STATIC e_dep.c)
+add_library(LinkObjectsEStatic STATIC e_lib.c)
+target_compile_definitions(LinkObjectsEObj PUBLIC OBJE)
+target_link_libraries(LinkObjectsE INTERFACE LinkObjectsEObj $<TARGET_OBJECTS:LinkObjectsEObj>)
+target_link_libraries(LinkObjectsEObj PRIVATE LinkObjectsEDep)
+target_link_libraries(LinkObjectsEStatic PRIVATE LinkObjectsE)
+target_link_libraries(LinkObjects PRIVATE LinkObjectsEStatic)
diff --git a/Tests/ObjectLibrary/LinkObjects/a_dep.c b/Tests/ObjectLibrary/LinkObjects/a_dep.c
new file mode 100644
index 000000000..01287405c
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/a_dep.c
@@ -0,0 +1,7 @@
+#ifdef OBJA
+# error "OBJA is defined, but should not be"
+#endif
+int a_dep(void)
+{
+ return 0;
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/a_obj.c b/Tests/ObjectLibrary/LinkObjects/a_obj.c
new file mode 100644
index 000000000..5e79c60c5
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/a_obj.c
@@ -0,0 +1,8 @@
+#ifndef OBJA
+# error "OBJA is not defined, but should be"
+#endif
+extern int a_dep(void);
+int a_obj(void)
+{
+ return a_dep();
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/b_dep.c b/Tests/ObjectLibrary/LinkObjects/b_dep.c
new file mode 100644
index 000000000..ad5d36737
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/b_dep.c
@@ -0,0 +1,7 @@
+#ifdef OBJB
+# error "OBJB is defined, but should not be"
+#endif
+int b_dep(void)
+{
+ return 0;
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/b_obj.c b/Tests/ObjectLibrary/LinkObjects/b_obj.c
new file mode 100644
index 000000000..d0f426a24
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/b_obj.c
@@ -0,0 +1,8 @@
+#ifndef OBJB
+# error "OBJB is not defined, but should be"
+#endif
+extern int b_dep(void);
+int b_obj(void)
+{
+ return b_dep();
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/c_dep.c b/Tests/ObjectLibrary/LinkObjects/c_dep.c
new file mode 100644
index 000000000..1d99ab874
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/c_dep.c
@@ -0,0 +1,7 @@
+#ifdef OBJC
+# error "OBJC is defined, but should not be"
+#endif
+int c_dep(void)
+{
+ return 0;
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/c_obj.c b/Tests/ObjectLibrary/LinkObjects/c_obj.c
new file mode 100644
index 000000000..08fa5f5bd
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/c_obj.c
@@ -0,0 +1,8 @@
+#ifndef OBJC
+# error "OBJC is not defined, but should be"
+#endif
+extern int c_dep(void);
+int c_obj(void)
+{
+ return c_dep();
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/d_dep.c b/Tests/ObjectLibrary/LinkObjects/d_dep.c
new file mode 100644
index 000000000..cf0931411
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/d_dep.c
@@ -0,0 +1,7 @@
+#ifdef OBJD
+# error "OBJD is defined, but should not be"
+#endif
+int d_dep(void)
+{
+ return 0;
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/d_obj.c b/Tests/ObjectLibrary/LinkObjects/d_obj.c
new file mode 100644
index 000000000..d14ce660e
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/d_obj.c
@@ -0,0 +1,8 @@
+#ifndef OBJD
+# error "OBJD is not defined, but should be"
+#endif
+extern int d_dep(void);
+int d_obj(void)
+{
+ return d_dep();
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/e_dep.c b/Tests/ObjectLibrary/LinkObjects/e_dep.c
new file mode 100644
index 000000000..7fb70c10a
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/e_dep.c
@@ -0,0 +1,7 @@
+#ifdef OBJE
+# error "OBJE is defined, but should not be"
+#endif
+int e_dep(void)
+{
+ return 0;
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/e_lib.c b/Tests/ObjectLibrary/LinkObjects/e_lib.c
new file mode 100644
index 000000000..9bb3a4435
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/e_lib.c
@@ -0,0 +1,5 @@
+extern int e_obj(void);
+int e_lib(void)
+{
+ return e_obj();
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/e_obj.c b/Tests/ObjectLibrary/LinkObjects/e_obj.c
new file mode 100644
index 000000000..02624ebfc
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/e_obj.c
@@ -0,0 +1,8 @@
+#ifndef OBJE
+# error "OBJE is not defined, but should be"
+#endif
+extern int e_dep(void);
+int e_obj(void)
+{
+ return e_dep();
+}
diff --git a/Tests/ObjectLibrary/LinkObjects/main.c b/Tests/ObjectLibrary/LinkObjects/main.c
new file mode 100644
index 000000000..c09c4f11b
--- /dev/null
+++ b/Tests/ObjectLibrary/LinkObjects/main.c
@@ -0,0 +1,24 @@
+#ifdef OBJA
+# error "OBJA is defined, but should not be"
+#endif
+#ifndef OBJB
+# error "OBJB is not defined, but should be"
+#endif
+#ifdef OBJC
+# error "OBJC is defined, but should not be"
+#endif
+#ifndef OBJD
+# error "OBJD is not defined, but should be"
+#endif
+#ifdef OBJE
+# error "OBJE is defined, but should not be"
+#endif
+extern int a_obj(void);
+extern int b_obj(void);
+extern int c_obj(void);
+extern int d_obj(void);
+extern int e_lib(void);
+int main(void)
+{
+ return a_obj() + b_obj() + c_obj() + d_obj() + e_lib();
+}
diff --git a/Tests/Plugin/CMakeLists.txt b/Tests/Plugin/CMakeLists.txt
index 729bba347..ec22bf436 100644
--- a/Tests/Plugin/CMakeLists.txt
+++ b/Tests/Plugin/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
cmake_policy(SET CMP0054 NEW)
project(Plugin)
@@ -46,7 +46,7 @@ target_link_libraries(example_mod_1 example_exe)
if(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG AND
"${CMAKE_C_CREATE_SHARED_MODULE}" MATCHES "SONAME_FLAG")
# Verify that targets export with proper IMPORTED SONAME properties.
- export(TARGETS example_mod_1 NAMESPACE exp_
+ export(TARGETS example_mod_1 example_exe NAMESPACE exp_
FILE ${CMAKE_CURRENT_BINARY_DIR}/mods.cmake)
include(ExternalProject)
diff --git a/Tests/PositionIndependentTargets/interface/CMakeLists.txt b/Tests/PositionIndependentTargets/interface/CMakeLists.txt
index 65f3b767e..90186a381 100644
--- a/Tests/PositionIndependentTargets/interface/CMakeLists.txt
+++ b/Tests/PositionIndependentTargets/interface/CMakeLists.txt
@@ -12,6 +12,9 @@ set_property(TARGET sharedlib PROPERTY DEFINE_SYMBOL PIC_TEST_BUILD_DLL)
add_executable(test_iface_via_shared "${CMAKE_CURRENT_SOURCE_DIR}/../pic_main.cpp")
target_link_libraries(test_iface_via_shared sharedlib)
+add_library(objectlib OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/../pic_lib.cpp")
+target_link_libraries(objectlib piciface)
+
add_library(sharedlibpic SHARED "${CMAKE_CURRENT_SOURCE_DIR}/../pic_lib.cpp")
set_property(TARGET sharedlibpic PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
set_property(TARGET sharedlibpic PROPERTY DEFINE_SYMBOL PIC_TEST_BUILD_DLL)
diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt
index bf2af645c..4347459f1 100644
--- a/Tests/Preprocess/CMakeLists.txt
+++ b/Tests/Preprocess/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.8.12)
project(Preprocess)
# This test is meant both as a test and as a reference for supported
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt
new file mode 100644
index 000000000..1f636af45
--- /dev/null
+++ b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt
@@ -0,0 +1,102 @@
+cmake_minimum_required(VERSION 3.17)
+project(RerunUicOnFileChange)
+include("../AutogenGuiTest.cmake")
+
+# Utility variables
+set(testProjectTemplateDir "${CMAKE_CURRENT_SOURCE_DIR}/UicOnFileChange")
+set(testProjectSrc "${CMAKE_CURRENT_BINARY_DIR}/UicOnFileChange")
+set(testProjectBinDir "${CMAKE_CURRENT_BINARY_DIR}/UicOnFileChange-build")
+
+set(TEST_CONFIG "Release")
+
+macro(sleep)
+ message(STATUS "Sleeping for a few seconds.")
+ execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
+endmacro()
+macro(rebuild buildName)
+ message(STATUS "Starting build ${buildName}.")
+ execute_process(COMMAND "${CMAKE_COMMAND}" --build . --config "${TEST_CONFIG}"
+ WORKING_DIRECTORY "${testProjectBinDir}" RESULT_VARIABLE result
+ )
+ if (result)
+ message(FATAL_ERROR "Build ${buildName} failed.")
+ else()
+ message(STATUS "Build ${buildName} finished.")
+ endif()
+endmacro()
+
+configure_file("${testProjectTemplateDir}/mocwidget.h" "${testProjectSrc}/mocwidget.h" COPYONLY)
+configure_file("${testProjectTemplateDir}/main.cpp" "${testProjectSrc}/main.cpp" COPYONLY)
+configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt" @ONLY)
+
+set(Num 1)
+configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY)
+
+if(CMAKE_GENERATOR_INSTANCE)
+ set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${CMAKE_GENERATOR_INSTANCE}")
+else()
+ set(_D_CMAKE_GENERATOR_INSTANCE "")
+endif()
+
+get_property(is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(is_multi)
+ set(build_type_extra "-DCMAKE_CONFIGURATION_TYPES=${TEST_CONFIG}")
+ set(extra_bin_path "${TEST_CONFIG}/")
+else()
+ set(build_type_extra "-DCMAKE_BUILD_TYPE=${TEST_CONFIG}")
+endif()
+
+# Set the environment PATH/LD_LIBRARY_PATH variables to run the resulting executable
+if(WIN32 AND TARGET ${QT_QTCORE_TARGET})
+ get_target_property(qtcore_path ${QT_QTCORE_TARGET} LOCATION)
+ if(NOT qtcore_path)
+ get_target_property(qtcore_path ${QT_QTCORE_TARGET} IMPORTED_LOCATION)
+ endif()
+ get_filename_component(qtcore_path "${qtcore_path}" DIRECTORY)
+ set(ENV{PATH} "${qtcore_path};$ENV{PATH}")
+endif()
+
+execute_process(
+ COMMAND "${CMAKE_COMMAND}" -B "${testProjectBinDir}" -S "${testProjectSrc}"
+ -G "${CMAKE_GENERATOR}"
+ -A "${CMAKE_GENERATOR_PLATFORM}"
+ -T "${CMAKE_GENERATOR_TOOLSET}"
+ ${_D_CMAKE_GENERATOR_INSTANCE}
+ "${build_type_extra}"
+ "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+ "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+ "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+ RESULT_VARIABLE exit_code
+ OUTPUT_VARIABLE output
+ ERROR_VARIABLE output
+)
+if(NOT exit_code EQUAL 0)
+ message(FATAL_ERROR "Initial configuration of UicOnFileChange failed. Output: ${output}")
+endif()
+
+# Initial build
+execute_process(
+ COMMAND "${CMAKE_COMMAND}" --build "${testProjectBinDir}" --config "${TEST_CONFIG}"
+ RESULT_VARIABLE exit_code
+ OUTPUT_VARIABLE output
+ ERROR_VARIABLE output
+)
+if(NOT exit_code EQUAL 0)
+ message(FATAL_ERROR "Initial build of UicOnFileChange failed. Output: ${output}")
+endif()
+
+execute_process(COMMAND "${testProjectBinDir}/${extra_bin_path}UicOnFileChange" RESULT_VARIABLE result)
+if(NOT result EQUAL "1")
+ message(FATAL_ERROR "Initial build of UicOnFileChange test result is: ${result}")
+endif()
+
+sleep()
+
+set(Num 2)
+configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY)
+rebuild(2)
+
+execute_process(COMMAND "${testProjectBinDir}/${extra_bin_path}UicOnFileChange" RESULT_VARIABLE result)
+if(NOT result EQUAL "0")
+ message(FATAL_ERROR "Rebuild of UicOnFileChange test result is: ${result}")
+endif()
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in
new file mode 100644
index 000000000..fa9dd6bee
--- /dev/null
+++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.10)
+
+project(UicOnFileChange)
+include("@CMAKE_CURRENT_LIST_DIR@/../AutogenGuiTest.cmake")
+
+# Enable CMAKE_AUTOUIC for all targets
+set(CMAKE_AUTOUIC ON)
+
+add_executable(UicOnFileChange main.cpp mainwindow.ui)
+target_include_directories(UicOnFileChange PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(UicOnFileChange ${QT_QTCORE_TARGET} ${QT_LIBRARIES})
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp
new file mode 100644
index 000000000..fd810fa24
--- /dev/null
+++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp
@@ -0,0 +1,9 @@
+#include "ui_mainwindow.h"
+
+int main(int argc, char* argv[])
+{
+ MocWidget mw;
+ Ui::Widget mwUi;
+ mwUi.setupUi(&mw);
+ return mw.objectName() == "Widget2" ? 0 : 1;
+}
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.ui.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.ui.in
new file mode 100644
index 000000000..8f39e5514
--- /dev/null
+++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.ui.in
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Widget</class>
+ <widget class="MocWidget" name="Widget@Num@"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mocwidget.h b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mocwidget.h
new file mode 100644
index 000000000..87fc177dd
--- /dev/null
+++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mocwidget.h
@@ -0,0 +1,5 @@
+#include <QtCore/QObject>
+
+class MocWidget : public QObject
+{
+};
diff --git a/Tests/QtAutogen/TestMacros.cmake b/Tests/QtAutogen/TestMacros.cmake
index 1024996ab..9dcf31fbd 100644
--- a/Tests/QtAutogen/TestMacros.cmake
+++ b/Tests/QtAutogen/TestMacros.cmake
@@ -43,6 +43,7 @@ macro(ADD_AUTOGEN_TEST NAME)
--build-options ${build_options} ${Autogen_BUILD_OPTIONS}
${_TestCommand}
)
+ set_tests_properties("${_QtXAutogen}.${NAME}" PROPERTIES LABELS "Qt${QT_TEST_VERSION}")
list(APPEND TEST_BUILD_DIRS "${_BuildDir}")
unset(_TestCommand)
unset(_QtXAutogen)
diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake
index b1337d626..a3c57a587 100644
--- a/Tests/QtAutogen/Tests.cmake
+++ b/Tests/QtAutogen/Tests.cmake
@@ -24,6 +24,7 @@ ADD_AUTOGEN_TEST(RerunMocOnAddFile)
ADD_AUTOGEN_TEST(RerunMocOnMissingDependency)
ADD_AUTOGEN_TEST(RerunRccConfigChange)
ADD_AUTOGEN_TEST(RerunRccDepends)
+ADD_AUTOGEN_TEST(RerunUicOnFileChange)
ADD_AUTOGEN_TEST(SameName sameName)
ADD_AUTOGEN_TEST(StaticLibraryCycle slc)
ADD_AUTOGEN_TEST(UicInclude uicInclude)
@@ -35,7 +36,9 @@ ADD_AUTOGEN_TEST(UnityMocSource)
if(QT_TEST_ALLOW_QT_MACROS)
ADD_AUTOGEN_TEST(MocCMP0071)
+ set_property(TEST "Qt${QT_TEST_VERSION}Autogen.MocCMP0071" APPEND PROPERTY LABELS "policy")
ADD_AUTOGEN_TEST(MocCMP0100)
+ set_property(TEST "Qt${QT_TEST_VERSION}Autogen.MocCMP0100" APPEND PROPERTY LABELS "policy")
ADD_AUTOGEN_TEST(MocInclude)
ADD_AUTOGEN_TEST(MocIncludeSymlink)
ADD_AUTOGEN_TEST(MocSkipSource)
@@ -46,6 +49,7 @@ if(QT_TEST_VERSION GREATER 4)
ADD_AUTOGEN_TEST(MocMacroName mocMacroName)
ADD_AUTOGEN_TEST(MocOsMacros)
ADD_AUTOGEN_TEST(RerunMocPlugin)
+ ADD_AUTOGEN_TEST(WrappedFindPackage)
if(APPLE)
ADD_AUTOGEN_TEST(MacOsFW)
endif()
diff --git a/Tests/QtAutogen/WrappedFindPackage/CMakeLists.txt b/Tests/QtAutogen/WrappedFindPackage/CMakeLists.txt
new file mode 100644
index 000000000..e8f50d56e
--- /dev/null
+++ b/Tests/QtAutogen/WrappedFindPackage/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.20)
+project(WrappedFindPackage)
+
+# Wrap the find_package call in a function.
+# Test whether AutoMoc can retrieve the Qt version from the moc executable.
+function(find_qt_package)
+ include("../AutogenCoreTest.cmake")
+ set(QT_LIBRARIES "${QT_LIBRARIES}" PARENT_SCOPE)
+endfunction()
+
+find_qt_package()
+
+set(CMAKE_AUTOMOC ON)
+
+add_executable(wrappedFindPackage main.cpp)
+target_link_libraries(wrappedFindPackage PRIVATE ${QT_LIBRARIES})
diff --git a/Tests/QtAutogen/WrappedFindPackage/main.cpp b/Tests/QtAutogen/WrappedFindPackage/main.cpp
new file mode 100644
index 000000000..1e2c63fab
--- /dev/null
+++ b/Tests/QtAutogen/WrappedFindPackage/main.cpp
@@ -0,0 +1,19 @@
+#include <qobject.h>
+
+class MyObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyObject(QObject* parent = 0)
+ : QObject(parent)
+ {
+ }
+};
+
+int main()
+{
+ MyObject obj;
+ return 0;
+}
+
+#include "main.moc"
diff --git a/Tests/ReturnTest/CMakeLists.txt b/Tests/ReturnTest/CMakeLists.txt
index c4c606c58..78e3fc1ca 100644
--- a/Tests/ReturnTest/CMakeLists.txt
+++ b/Tests/ReturnTest/CMakeLists.txt
@@ -1,5 +1,5 @@
# a simple C only test case
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project (ReturnTest)
function (FAILED testname)
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake
index 01eac91dd..e4fdb4ae5 100644
--- a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake
@@ -3,15 +3,15 @@ enable_language(C)
add_custom_command(
OUTPUT topcc.c
- DEPFILE topcc.c.d
- COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_CURRENT_BINARY_DIR}/topcc.c -DINFILE=topccdep.txt -DDEPFILE=topcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
+ DEPFILE topcc_$<CONFIG>.c.d
+ COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_CURRENT_BINARY_DIR}/topcc.c -DINFILE=topccdep.txt -DDEPFILE=topcc_$<CONFIG>.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
)
add_custom_target(topcc ALL DEPENDS topcc.c)
add_custom_command(
OUTPUT topexe.c
- DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/topexe.c.d
- COMMAND ${CMAKE_COMMAND} -DOUTFILE=topexe.c "-DINFILE=${CMAKE_CURRENT_BINARY_DIR}/topexedep.txt" -DDEPFILE=topexe.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
+ DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/topexe_$<CONFIG>.c.d
+ COMMAND ${CMAKE_COMMAND} -DOUTFILE=topexe.c "-DINFILE=${CMAKE_CURRENT_BINARY_DIR}/topexedep.txt" -DDEPFILE=topexe_$<CONFIG>.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
)
add_executable(topexe "${CMAKE_CURRENT_BINARY_DIR}/topexe.c")
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake
new file mode 100644
index 000000000..22e7f2733
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake
@@ -0,0 +1,19 @@
+enable_language(C)
+
+add_custom_command(
+ OUTPUT main.c
+ COMMAND ${CMAKE_COMMAND} -E copy main.c.in main.c
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/main.c.in
+ )
+add_executable(main main.c)
+set_property(TARGET main PROPERTY UNITY_BUILD ON)
+
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
+set(check_pairs
+ \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c.in\"
+ \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c\"
+ )
+set(check_exes
+ \"$<TARGET_FILE:main>\"
+ )
+")
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake
new file mode 100644
index 000000000..87576ebf0
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake
@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[
+int main(void) { return 1; }
+]])
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake
new file mode 100644
index 000000000..69b21b831
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake
@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[
+int main(void) { return 2; }
+]])
diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
index 62326345e..f8c20c2ea 100644
--- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
+++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
@@ -1,5 +1,22 @@
include(RunCMake)
+if(RunCMake_GENERATOR MATCHES "Ninja")
+ # Detect ninja version so we know what tests can be supported.
+ execute_process(
+ COMMAND "${RunCMake_MAKE_PROGRAM}" --version
+ OUTPUT_VARIABLE ninja_out
+ ERROR_VARIABLE ninja_out
+ RESULT_VARIABLE ninja_res
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(ninja_res EQUAL 0 AND "x${ninja_out}" MATCHES "^x[0-9]+\\.[0-9]+")
+ set(ninja_version "${ninja_out}")
+ message(STATUS "ninja version: ${ninja_version}")
+ else()
+ message(FATAL_ERROR "'ninja --version' reported:\n${ninja_out}")
+ endif()
+endif()
+
if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR
RunCMake_GENERATOR STREQUAL "Watcom WMake")
set(fs_delay 3)
@@ -155,7 +172,8 @@ if (RunCMake_GENERATOR MATCHES "Makefiles")
run_cmake(CustomCommandDependencies-BadArgs)
endif()
-if(RunCMake_GENERATOR MATCHES "Make|Ninja")
+if(RunCMake_GENERATOR MATCHES "Make|Ninja|Visual Studio|Xcode" AND
+ NOT RunCMake_GENERATOR MATCHES "Visual Studio (9|10)( |$)")
unset(run_BuildDepends_skip_step_3)
run_BuildDepends(CustomCommandDepfile)
set(run_BuildDepends_skip_step_3 1)
@@ -164,3 +182,11 @@ endif()
if(RunCMake_GENERATOR MATCHES "Make")
run_BuildDepends(MakeDependencies)
endif()
+
+if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 " OR
+ (RunCMake_GENERATOR MATCHES "Ninja" AND ninja_version VERSION_LESS 1.7))
+ # This build tool misses the dependency.
+ set(run_BuildDepends_skip_step_2 1)
+endif()
+run_BuildDepends(CustomCommandUnityBuild)
+unset(run_BuildDepends_skip_step_2)
diff --git a/Tests/RunCMake/BundleUtilities/CMP0080-COMMAND-OLD-stderr.txt b/Tests/RunCMake/BundleUtilities/CMP0080-COMMAND-OLD-stderr.txt
new file mode 100644
index 000000000..31a0207fb
--- /dev/null
+++ b/Tests/RunCMake/BundleUtilities/CMP0080-COMMAND-OLD-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Deprecation Warning at [^
+]*/Tests/RunCMake/BundleUtilities/CMP0080-COMMAND.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0080 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.$
diff --git a/Tests/RunCMake/BundleUtilities/CMP0080-OLD-stderr.txt b/Tests/RunCMake/BundleUtilities/CMP0080-OLD-stderr.txt
new file mode 100644
index 000000000..2ff5d6035
--- /dev/null
+++ b/Tests/RunCMake/BundleUtilities/CMP0080-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0080-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0080 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/CMP0041/RunCMakeTest.cmake b/Tests/RunCMake/CMP0041/RunCMakeTest.cmake
index e7f27a1a2..f47bb2ee3 100644
--- a/Tests/RunCMake/CMP0041/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMP0041/RunCMakeTest.cmake
@@ -6,6 +6,10 @@ set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/NotDefa
run_cmake(CMP0041-OLD)
run_cmake(CMP0041-NEW)
run_cmake(CMP0041-WARN)
+
+# Protect tests from running inside the default install prefix.
+set(RunCMake_TEST_OPTIONS "--install-prefix ${RunCMake_BINARY_DIR}/NotDefaultPrefix")
+
run_cmake(CMP0041-tid-OLD)
run_cmake(CMP0041-tid-NEW)
run_cmake(CMP0041-tid-WARN)
diff --git a/Tests/RunCMake/CMP0081/CMP0081-OLD-result.txt b/Tests/RunCMake/CMP0081/CMP0081-OLD-result.txt
deleted file mode 100644
index 573541ac9..000000000
--- a/Tests/RunCMake/CMP0081/CMP0081-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0081/CMP0081-OLD-stderr.txt b/Tests/RunCMake/CMP0081/CMP0081-OLD-stderr.txt
new file mode 100644
index 000000000..ff339fa04
--- /dev/null
+++ b/Tests/RunCMake/CMP0081/CMP0081-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0081-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0081 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/CMP0121/CMP0121-ERANGE-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-Common.cmake
new file mode 100644
index 000000000..5594be811
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-Common.cmake
@@ -0,0 +1,8 @@
+set(listvar a b c d e)
+
+list(GET listvar
+ 18446744073709551616 # 2^64
+ 2147483648 # 2^31
+ 4294967296 # 2^32; errors out-of-range as -2147483643 due to underflow
+ out)
+message("ERANGE: -->${out}<--")
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-result.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-result.txt
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-result.txt
diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-stderr.txt
new file mode 100644
index 000000000..0166e1444
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\):
+ list index: 18446744073709551616 is not a valid index
+Call Stack \(most recent call first\):
+ CMP0121-ERANGE-NEW.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+
+
+ERANGE: --><--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW.cmake
new file mode 100644
index 000000000..68e564d55
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 NEW)
+include(CMP0121-ERANGE-Common.cmake)
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-result.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-result.txt
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-result.txt
diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt
new file mode 100644
index 000000000..5a035596e
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\):
+ list index: (-2147483643|2147483647) out of range \(-5, 4\)
+Call Stack \(most recent call first\):
+ CMP0121-ERANGE-OLD.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+
+
+ERANGE: --><--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD.cmake
new file mode 100644
index 000000000..32f0b5669
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 OLD)
+include(CMP0121-ERANGE-Common.cmake)
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-result.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-result.txt
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-result.txt
diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt
new file mode 100644
index 000000000..1e7b12757
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt
@@ -0,0 +1,18 @@
+CMake Warning \(dev\) at CMP0121-ERANGE-Common.cmake:3 \(list\):
+ Policy CMP0121 is not set: The list\(\) command now validates parsing of
+ index arguments. Run "cmake --help-policy CMP0121" for policy details.
+ Use the cmake_policy command to set the policy and suppress this warning.
+ Invalid list index "18446744073709551616".
+Call Stack \(most recent call first\):
+ CMP0121-ERANGE-WARN.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\):
+ list index: (-2147483643|2147483647) out of range \(-5, 4\)
+Call Stack \(most recent call first\):
+ CMP0121-ERANGE-WARN.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+
+
+ERANGE: --><--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN.cmake
new file mode 100644
index 000000000..96552906a
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0121-ERANGE-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-GET-Common.cmake
new file mode 100644
index 000000000..e4986f02d
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-GET-Common.cmake
@@ -0,0 +1,4 @@
+set(listvar a b c d e)
+
+list(GET listvar 0 2junk out)
+message("GET: -->${out}<--")
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-result.txt b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-result.txt
+++ b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-result.txt
diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-stderr.txt
new file mode 100644
index 000000000..d502b869a
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at CMP0121-GET-Common.cmake:3 \(list\):
+ list index: 2junk is not a valid index
+Call Stack \(most recent call first\):
+ CMP0121-GET-NEW.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+
+
+GET: --><--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW.cmake
new file mode 100644
index 000000000..1ab054de5
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 NEW)
+include(CMP0121-GET-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-GET-OLD-stderr.txt
new file mode 100644
index 000000000..96375e995
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-GET-OLD-stderr.txt
@@ -0,0 +1 @@
+GET: -->a;c<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-GET-OLD.cmake
new file mode 100644
index 000000000..ef4526f42
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-GET-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 OLD)
+include(CMP0121-GET-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-GET-WARN-stderr.txt
new file mode 100644
index 000000000..ecfad2cab
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-GET-WARN-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at CMP0121-GET-Common.cmake:3 \(list\):
+ Policy CMP0121 is not set: The list\(\) command now validates parsing of
+ index arguments. Run "cmake --help-policy CMP0121" for policy details.
+ Use the cmake_policy command to set the policy and suppress this warning.
+ Invalid list index "2junk".
+Call Stack \(most recent call first\):
+ CMP0121-GET-WARN.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+GET: -->a;c<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-GET-WARN.cmake
new file mode 100644
index 000000000..b08620b5b
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-GET-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0121-GET-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-INSERT-Common.cmake
new file mode 100644
index 000000000..495088102
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-Common.cmake
@@ -0,0 +1,4 @@
+set(listvar a b c d e)
+
+list(INSERT listvar junk2 new)
+message("INSERT: -->${listvar}<--")
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-result.txt b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-result.txt
+++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-result.txt
diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-stderr.txt
new file mode 100644
index 000000000..224196273
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at CMP0121-INSERT-Common.cmake:3 \(list\):
+ list index: junk2 is not a valid index
+Call Stack \(most recent call first\):
+ CMP0121-INSERT-NEW.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+
+
+INSERT: -->a;b;c;d;e<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW.cmake
new file mode 100644
index 000000000..db627d137
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 NEW)
+include(CMP0121-INSERT-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD-stderr.txt
new file mode 100644
index 000000000..52f34ad5d
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD-stderr.txt
@@ -0,0 +1 @@
+INSERT: -->new;a;b;c;d;e<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD.cmake
new file mode 100644
index 000000000..60364d70f
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 OLD)
+include(CMP0121-INSERT-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN-stderr.txt
new file mode 100644
index 000000000..5fa7d17ef
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at CMP0121-INSERT-Common.cmake:3 \(list\):
+ Policy CMP0121 is not set: The list\(\) command now validates parsing of
+ index arguments. Run "cmake --help-policy CMP0121" for policy details.
+ Use the cmake_policy command to set the policy and suppress this warning.
+ Invalid list index "junk2".
+Call Stack \(most recent call first\):
+ CMP0121-INSERT-WARN.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+INSERT: -->new;a;b;c;d;e<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN.cmake
new file mode 100644
index 000000000..55f13e222
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0121-INSERT-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-Common.cmake
new file mode 100644
index 000000000..ec9238774
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-Common.cmake
@@ -0,0 +1,4 @@
+set(listvar a b c d e)
+
+list(REMOVE_AT listvar 0 invalid)
+message("REMOVE_AT: -->${listvar}<--")
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-result.txt b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-result.txt
+++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-result.txt
diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-stderr.txt
new file mode 100644
index 000000000..f17bafd19
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at CMP0121-REMOVE_AT-Common.cmake:3 \(list\):
+ list index: invalid is not a valid index
+Call Stack \(most recent call first\):
+ CMP0121-REMOVE_AT-NEW.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+
+
+REMOVE_AT: -->a;b;c;d;e<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW.cmake
new file mode 100644
index 000000000..d1f09e374
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 NEW)
+include(CMP0121-REMOVE_AT-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD-stderr.txt
new file mode 100644
index 000000000..09af1ae53
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD-stderr.txt
@@ -0,0 +1 @@
+REMOVE_AT: -->b;c;d;e<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD.cmake
new file mode 100644
index 000000000..ac83226aa
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 OLD)
+include(CMP0121-REMOVE_AT-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN-stderr.txt
new file mode 100644
index 000000000..e2d47af58
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at CMP0121-REMOVE_AT-Common.cmake:3 \(list\):
+ Policy CMP0121 is not set: The list\(\) command now validates parsing of
+ index arguments. Run "cmake --help-policy CMP0121" for policy details.
+ Use the cmake_policy command to set the policy and suppress this warning.
+ Invalid list index "invalid".
+Call Stack \(most recent call first\):
+ CMP0121-REMOVE_AT-WARN.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+REMOVE_AT: -->b;c;d;e<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN.cmake
new file mode 100644
index 000000000..2b4a8245a
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0121-REMOVE_AT-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-Common.cmake
new file mode 100644
index 000000000..93f46c5fc
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-Common.cmake
@@ -0,0 +1,4 @@
+set(listvar a b c d e)
+
+list(SUBLIST listvar 0 invalid out)
+message("SUBLIST-length: -->${out}<--")
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-result.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-result.txt
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-result.txt
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-stderr.txt
new file mode 100644
index 000000000..28bd36216
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at CMP0121-SUBLIST-length-Common.cmake:3 \(list\):
+ list index: invalid is not a valid index
+Call Stack \(most recent call first\):
+ CMP0121-SUBLIST-length-NEW.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+
+
+SUBLIST-length: --><--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW.cmake
new file mode 100644
index 000000000..c7875cb6c
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 NEW)
+include(CMP0121-SUBLIST-length-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD-stderr.txt
new file mode 100644
index 000000000..00fcf07fe
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD-stderr.txt
@@ -0,0 +1 @@
+SUBLIST-length: --><--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD.cmake
new file mode 100644
index 000000000..e9b78eebd
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 OLD)
+include(CMP0121-SUBLIST-length-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN-stderr.txt
new file mode 100644
index 000000000..bd06c2f70
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at CMP0121-SUBLIST-length-Common.cmake:3 \(list\):
+ Policy CMP0121 is not set: The list\(\) command now validates parsing of
+ index arguments. Run "cmake --help-policy CMP0121" for policy details.
+ Use the cmake_policy command to set the policy and suppress this warning.
+ Invalid list index "invalid".
+Call Stack \(most recent call first\):
+ CMP0121-SUBLIST-length-WARN.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+SUBLIST-length: --><--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN.cmake
new file mode 100644
index 000000000..27318bfa9
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0121-SUBLIST-length-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-Common.cmake
new file mode 100644
index 000000000..33f57a336
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-Common.cmake
@@ -0,0 +1,4 @@
+set(listvar a b c d e)
+
+list(SUBLIST listvar invalid 2 out)
+message("SUBLIST-start: -->${out}<--")
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-result.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-result.txt
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-result.txt
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-stderr.txt
new file mode 100644
index 000000000..9819f95e4
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at CMP0121-SUBLIST-start-Common.cmake:3 \(list\):
+ list index: invalid is not a valid index
+Call Stack \(most recent call first\):
+ CMP0121-SUBLIST-start-NEW.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+
+
+SUBLIST-start: --><--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW.cmake
new file mode 100644
index 000000000..3d676a3f3
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 NEW)
+include(CMP0121-SUBLIST-start-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD-stderr.txt
new file mode 100644
index 000000000..8da2881d6
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD-stderr.txt
@@ -0,0 +1 @@
+SUBLIST-start: -->a;b<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD.cmake
new file mode 100644
index 000000000..268f317e1
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0121 OLD)
+include(CMP0121-SUBLIST-start-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN-stderr.txt
new file mode 100644
index 000000000..39d0e0ee9
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at CMP0121-SUBLIST-start-Common.cmake:3 \(list\):
+ Policy CMP0121 is not set: The list\(\) command now validates parsing of
+ index arguments. Run "cmake --help-policy CMP0121" for policy details.
+ Use the cmake_policy command to set the policy and suppress this warning.
+ Invalid list index "invalid".
+Call Stack \(most recent call first\):
+ CMP0121-SUBLIST-start-WARN.cmake:2 \(include\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+SUBLIST-start: -->a;b<--
diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN.cmake
new file mode 100644
index 000000000..a40787956
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0121-SUBLIST-start-Common.cmake)
diff --git a/Tests/RunCMake/CMP0121/CMakeLists.txt b/Tests/RunCMake/CMP0121/CMakeLists.txt
new file mode 100644
index 000000000..7cabeb68b
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.20)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0121/RunCMakeTest.cmake b/Tests/RunCMake/CMP0121/RunCMakeTest.cmake
new file mode 100644
index 000000000..1ed5b1a5d
--- /dev/null
+++ b/Tests/RunCMake/CMP0121/RunCMakeTest.cmake
@@ -0,0 +1,7 @@
+include(RunCMake)
+
+foreach (subcommand IN ITEMS ERANGE GET INSERT REMOVE_AT SUBLIST-length SUBLIST-start)
+ run_cmake(CMP0121-${subcommand}-WARN)
+ run_cmake(CMP0121-${subcommand}-OLD)
+ run_cmake(CMP0121-${subcommand}-NEW)
+endforeach ()
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-Common.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_file-Common.cmake
new file mode 100644
index 000000000..a85978bf6
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-Common.cmake
@@ -0,0 +1,51 @@
+
+find_file(RELATIVE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_file(RELATIVE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_file(ABSOLUTE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_file(ABSOLUTE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_file(NOTFOUND_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_file(NOTFOUND_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+file(WRITE "${CMAKE_BINARY_DIR}/${FILE_NAME}" "")
+find_file(FILE_NAME NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_file(FILE_NAME_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+message("RELATIVE_PATH=${RELATIVE_PATH}")
+message("RELATIVE_PATH_WITH_TYPE=${RELATIVE_PATH_WITH_TYPE}")
+
+message("ABSOLUTE_PATH=${ABSOLUTE_PATH}")
+message("ABSOLUTE_PATH_WITH_TYPE=${ABSOLUTE_PATH_WITH_TYPE}")
+
+message("NOTFOUND_PATH=${NOTFOUND_PATH}")
+message("NOTFOUND_PATH_WITH_TYPE=${NOTFOUND_PATH_WITH_TYPE}")
+
+message("FILE_NAME=${FILE_NAME}")
+message("FILE_NAME_WITH_TYPE=${FILE_NAME_WITH_TYPE}")
+
+
+set(RELATIVE_PATH_AND_LOCAL relative_local)
+set(RELATIVE_PATH_WITH_TYPE_AND_LOCAL relative_local)
+set(ABSOLUTE_PATH_AND_LOCAL /absolute_local)
+set(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL /absolute_local)
+set(NOTFOUND_AND_LOCAL "${FILE_NAME}")
+set(NOTFOUND_WITH_TYPE_AND_LOCAL "${FILE_NAME}")
+
+find_file(RELATIVE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_file(RELATIVE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_file(ABSOLUTE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_file(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_file(NOTFOUND_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_file(NOTFOUND_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+message("RELATIVE_PATH_AND_LOCAL=${RELATIVE_PATH_AND_LOCAL}")
+message("RELATIVE_PATH_WITH_TYPE_AND_LOCAL=${RELATIVE_PATH_WITH_TYPE_AND_LOCAL}")
+
+message("ABSOLUTE_PATH_AND_LOCAL=${ABSOLUTE_PATH_AND_LOCAL}")
+message("ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=${ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL}")
+
+message("NOTFOUND_PATH_AND_LOCAL=${NOTFOUND_PATH_AND_LOCAL}")
+message("NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=${NOTFOUND_PATH_WITH_TYPE_AND_LOCAL}")
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW-stderr.txt
new file mode 100644
index 000000000..10f95bcbd
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW-stderr.txt
@@ -0,0 +1,14 @@
+RELATIVE_PATH=relative
+RELATIVE_PATH_WITH_TYPE=relative
+ABSOLUTE_PATH=/absolute
+ABSOLUTE_PATH_WITH_TYPE=/absolute
+NOTFOUND_PATH=/.+/CMP0125/file\.txt
+NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/file\.txt
+FILE_NAME=/.+/CMP0125/CMP0125-find_file-NEW-build/file2\.txt
+FILE_NAME_WITH_TYPE=/.+/CMP0125/CMP0125-find_file-NEW-build/file2\.txt
+RELATIVE_PATH_AND_LOCAL=relative_local
+RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local
+ABSOLUTE_PATH_AND_LOCAL=/absolute_local
+ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local
+NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125/file.txt
+NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/file.txt
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW.cmake
new file mode 100644
index 000000000..4f0483499
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0125 NEW)
+
+include(CMP0125-find_file-Common.cmake)
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD-stderr.txt
new file mode 100644
index 000000000..5b25f9227
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD-stderr.txt
@@ -0,0 +1,14 @@
+RELATIVE_PATH=/.+/CMP0125/CMP0125-find_file-OLD-build/relative
+RELATIVE_PATH_WITH_TYPE=relative
+ABSOLUTE_PATH=/absolute
+ABSOLUTE_PATH_WITH_TYPE=/absolute
+NOTFOUND_PATH=NOTFOUND
+NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/file\.txt
+FILE_NAME=/.+/CMP0125/CMP0125-find_file-OLD-build/file2\.txt
+FILE_NAME_WITH_TYPE=file2\.txt
+RELATIVE_PATH_AND_LOCAL=/.+/CMP0125/CMP0125-find_file-OLD-build/relative
+RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local
+ABSOLUTE_PATH_AND_LOCAL=/absolute
+ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local
+NOTFOUND_PATH_AND_LOCAL=NOTFOUND
+NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/file\.txt
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD.cmake
new file mode 100644
index 000000000..21884b5a8
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0125 OLD)
+
+include(CMP0125-find_file-Common.cmake)
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-Common.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_library-Common.cmake
new file mode 100644
index 000000000..d2bc0062a
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-Common.cmake
@@ -0,0 +1,52 @@
+
+find_library(RELATIVE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_library(RELATIVE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_library(ABSOLUTE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_library(ABSOLUTE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_library(NOTFOUND_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_library(NOTFOUND_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+file(WRITE "${CMAKE_BINARY_DIR}/${FILE_NAME}" "")
+file(CHMOD "${CMAKE_BINARY_DIR}/${FILE_NAME}" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE)
+find_library(FILE_NAME NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_library(FILE_NAME_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+message("RELATIVE_PATH=${RELATIVE_PATH}")
+message("RELATIVE_PATH_WITH_TYPE=${RELATIVE_PATH_WITH_TYPE}")
+
+message("ABSOLUTE_PATH=${ABSOLUTE_PATH}")
+message("ABSOLUTE_PATH_WITH_TYPE=${ABSOLUTE_PATH_WITH_TYPE}")
+
+message("NOTFOUND_PATH=${NOTFOUND_PATH}")
+message("NOTFOUND_PATH_WITH_TYPE=${NOTFOUND_PATH_WITH_TYPE}")
+
+message("FILE_NAME=${FILE_NAME}")
+message("FILE_NAME_WITH_TYPE=${FILE_NAME_WITH_TYPE}")
+
+
+set(RELATIVE_PATH_AND_LOCAL relative_local)
+set(RELATIVE_PATH_WITH_TYPE_AND_LOCAL relative_local)
+set(ABSOLUTE_PATH_AND_LOCAL /absolute_local)
+set(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL /absolute_local)
+set(NOTFOUND_AND_LOCAL "${FILE_NAME}")
+set(NOTFOUND_WITH_TYPE_AND_LOCAL "${FILE_NAME}")
+
+find_library(RELATIVE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_library(RELATIVE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_library(ABSOLUTE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_library(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_library(NOTFOUND_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_library(NOTFOUND_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+message("RELATIVE_PATH_AND_LOCAL=${RELATIVE_PATH_AND_LOCAL}")
+message("RELATIVE_PATH_WITH_TYPE_AND_LOCAL=${RELATIVE_PATH_WITH_TYPE_AND_LOCAL}")
+
+message("ABSOLUTE_PATH_AND_LOCAL=${ABSOLUTE_PATH_AND_LOCAL}")
+message("ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=${ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL}")
+
+message("NOTFOUND_PATH_AND_LOCAL=${NOTFOUND_PATH_AND_LOCAL}")
+message("NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=${NOTFOUND_PATH_WITH_TYPE_AND_LOCAL}")
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW-stderr.txt
new file mode 100644
index 000000000..d180833e7
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW-stderr.txt
@@ -0,0 +1,14 @@
+RELATIVE_PATH=relative
+RELATIVE_PATH_WITH_TYPE=relative
+ABSOLUTE_PATH=/absolute
+ABSOLUTE_PATH_WITH_TYPE=/absolute
+NOTFOUND_PATH=/.+/CMP0125/libfile\.(so|dylib)
+NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/libfile\.(so|dylib)
+FILE_NAME=/.+/CMP0125/CMP0125-find_library-NEW-build/libfile2\.(so|dylib)
+FILE_NAME_WITH_TYPE=/.+/CMP0125/CMP0125-find_library-NEW-build/libfile2\.(so|dylib)
+RELATIVE_PATH_AND_LOCAL=relative_local
+RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local
+ABSOLUTE_PATH_AND_LOCAL=/absolute_local
+ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local
+NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125/libfile.(so|dylib)
+NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/libfile.(so|dylib)
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW.cmake
new file mode 100644
index 000000000..31f5441cd
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW.cmake
@@ -0,0 +1,6 @@
+
+cmake_policy(SET CMP0125 NEW)
+
+enable_language(C)
+
+include(CMP0125-find_library-Common.cmake)
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD-stderr.txt
new file mode 100644
index 000000000..cd3af5669
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD-stderr.txt
@@ -0,0 +1,14 @@
+RELATIVE_PATH=/.+/CMP0125/CMP0125-find_library-OLD-build/relative
+RELATIVE_PATH_WITH_TYPE=relative
+ABSOLUTE_PATH=/absolute
+ABSOLUTE_PATH_WITH_TYPE=/absolute
+NOTFOUND_PATH=NOTFOUND
+NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/libfile\.(so|dylib)
+FILE_NAME=/.+/CMP0125/CMP0125-find_library-OLD-build/libfile2\.(so|dylib)
+FILE_NAME_WITH_TYPE=libfile2\.(so|dylib)
+RELATIVE_PATH_AND_LOCAL=relative_local
+RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local
+ABSOLUTE_PATH_AND_LOCAL=/absolute_local
+ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local
+NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125/libfile\.(so|dylib)
+NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/libfile\.(so|dylib)
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD.cmake
new file mode 100644
index 000000000..1dc4a95f5
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD.cmake
@@ -0,0 +1,6 @@
+
+cmake_policy(SET CMP0125 OLD)
+
+enable_language(C)
+
+include(CMP0125-find_library-Common.cmake)
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-Common.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_path-Common.cmake
new file mode 100644
index 000000000..37680c2a3
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-Common.cmake
@@ -0,0 +1,51 @@
+
+find_path(RELATIVE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_path(RELATIVE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_path(ABSOLUTE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_path(ABSOLUTE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_path(NOTFOUND_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_path(NOTFOUND_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+file(WRITE "${CMAKE_BINARY_DIR}/${FILE_NAME}" "")
+find_path(FILE_NAME NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_path(FILE_NAME_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+message("RELATIVE_PATH=${RELATIVE_PATH}")
+message("RELATIVE_PATH_WITH_TYPE=${RELATIVE_PATH_WITH_TYPE}")
+
+message("ABSOLUTE_PATH=${ABSOLUTE_PATH}")
+message("ABSOLUTE_PATH_WITH_TYPE=${ABSOLUTE_PATH_WITH_TYPE}")
+
+message("NOTFOUND_PATH=${NOTFOUND_PATH}")
+message("NOTFOUND_PATH_WITH_TYPE=${NOTFOUND_PATH_WITH_TYPE}")
+
+message("FILE_NAME=${FILE_NAME}")
+message("FILE_NAME_WITH_TYPE=${FILE_NAME_WITH_TYPE}")
+
+
+set(RELATIVE_PATH_AND_LOCAL relative_local)
+set(RELATIVE_PATH_WITH_TYPE_AND_LOCAL relative_local)
+set(ABSOLUTE_PATH_AND_LOCAL /absolute_local)
+set(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL /absolute_local)
+set(NOTFOUND_AND_LOCAL "${FILE_NAME}")
+set(NOTFOUND_WITH_TYPE_AND_LOCAL "${FILE_NAME}")
+
+find_path(RELATIVE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_path(RELATIVE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_path(ABSOLUTE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_path(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_path(NOTFOUND_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_path(NOTFOUND_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+message("RELATIVE_PATH_AND_LOCAL=${RELATIVE_PATH_AND_LOCAL}")
+message("RELATIVE_PATH_WITH_TYPE_AND_LOCAL=${RELATIVE_PATH_WITH_TYPE_AND_LOCAL}")
+
+message("ABSOLUTE_PATH_AND_LOCAL=${ABSOLUTE_PATH_AND_LOCAL}")
+message("ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=${ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL}")
+
+message("NOTFOUND_PATH_AND_LOCAL=${NOTFOUND_PATH_AND_LOCAL}")
+message("NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=${NOTFOUND_PATH_WITH_TYPE_AND_LOCAL}")
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW-stderr.txt
new file mode 100644
index 000000000..c3f02083d
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW-stderr.txt
@@ -0,0 +1,14 @@
+RELATIVE_PATH=relative
+RELATIVE_PATH_WITH_TYPE=relative
+ABSOLUTE_PATH=/absolute
+ABSOLUTE_PATH_WITH_TYPE=/absolute
+NOTFOUND_PATH=/.+/CMP0125
+NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125
+FILE_NAME=/.+/CMP0125/CMP0125-find_path-NEW-build/file2\.txt
+FILE_NAME_WITH_TYPE=/.+/CMP0125/CMP0125-find_path-NEW-build/file2\.txt
+RELATIVE_PATH_AND_LOCAL=relative_local
+RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local
+ABSOLUTE_PATH_AND_LOCAL=/absolute_local
+ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local
+NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125
+NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW.cmake
new file mode 100644
index 000000000..d6a854404
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0125 NEW)
+
+include(CMP0125-find_path-Common.cmake)
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD-stderr.txt
new file mode 100644
index 000000000..b84c8695a
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD-stderr.txt
@@ -0,0 +1,14 @@
+RELATIVE_PATH=/.+/CMP0125/CMP0125-find_path-OLD-build/relative
+RELATIVE_PATH_WITH_TYPE=relative
+ABSOLUTE_PATH=/absolute
+ABSOLUTE_PATH_WITH_TYPE=/absolute
+NOTFOUND_PATH=NOTFOUND
+NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125
+FILE_NAME=/.+/CMP0125/CMP0125-find_path-OLD-build/file2\.txt
+FILE_NAME_WITH_TYPE=file2\.txt
+RELATIVE_PATH_AND_LOCAL=/.+/CMP0125/CMP0125-find_path-OLD-build/relative
+RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local
+ABSOLUTE_PATH_AND_LOCAL=/absolute
+ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local
+NOTFOUND_PATH_AND_LOCAL=NOTFOUND
+NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD.cmake
new file mode 100644
index 000000000..2e98ded01
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0125 OLD)
+
+include(CMP0125-find_path-Common.cmake)
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-Common.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_program-Common.cmake
new file mode 100644
index 000000000..fee4c348b
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-Common.cmake
@@ -0,0 +1,52 @@
+
+find_program(RELATIVE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_program(RELATIVE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_program(ABSOLUTE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_program(ABSOLUTE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_program(NOTFOUND_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_program(NOTFOUND_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+file(WRITE "${CMAKE_BINARY_DIR}/${FILE_NAME}" "")
+file(CHMOD "${CMAKE_BINARY_DIR}/${FILE_NAME}" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE)
+find_program(FILE_NAME NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_program(FILE_NAME_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+message("RELATIVE_PATH=${RELATIVE_PATH}")
+message("RELATIVE_PATH_WITH_TYPE=${RELATIVE_PATH_WITH_TYPE}")
+
+message("ABSOLUTE_PATH=${ABSOLUTE_PATH}")
+message("ABSOLUTE_PATH_WITH_TYPE=${ABSOLUTE_PATH_WITH_TYPE}")
+
+message("NOTFOUND_PATH=${NOTFOUND_PATH}")
+message("NOTFOUND_PATH_WITH_TYPE=${NOTFOUND_PATH_WITH_TYPE}")
+
+message("FILE_NAME=${FILE_NAME}")
+message("FILE_NAME_WITH_TYPE=${FILE_NAME_WITH_TYPE}")
+
+
+set(RELATIVE_PATH_AND_LOCAL relative_local)
+set(RELATIVE_PATH_WITH_TYPE_AND_LOCAL relative_local)
+set(ABSOLUTE_PATH_AND_LOCAL /absolute_local)
+set(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL /absolute_local)
+set(NOTFOUND_AND_LOCAL "${FILE_NAME}")
+set(NOTFOUND_WITH_TYPE_AND_LOCAL "${FILE_NAME}")
+
+find_program(RELATIVE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_program(RELATIVE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_program(ABSOLUTE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_program(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+find_program(NOTFOUND_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+find_program(NOTFOUND_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH})
+
+message("RELATIVE_PATH_AND_LOCAL=${RELATIVE_PATH_AND_LOCAL}")
+message("RELATIVE_PATH_WITH_TYPE_AND_LOCAL=${RELATIVE_PATH_WITH_TYPE_AND_LOCAL}")
+
+message("ABSOLUTE_PATH_AND_LOCAL=${ABSOLUTE_PATH_AND_LOCAL}")
+message("ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=${ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL}")
+
+message("NOTFOUND_PATH_AND_LOCAL=${NOTFOUND_PATH_AND_LOCAL}")
+message("NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=${NOTFOUND_PATH_WITH_TYPE_AND_LOCAL}")
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW-stderr.txt
new file mode 100644
index 000000000..62da5bf0b
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW-stderr.txt
@@ -0,0 +1,14 @@
+RELATIVE_PATH=relative
+RELATIVE_PATH_WITH_TYPE=relative
+ABSOLUTE_PATH=/absolute
+ABSOLUTE_PATH_WITH_TYPE=/absolute
+NOTFOUND_PATH=/.+/CMP0125/file\.txt
+NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/file\.txt
+FILE_NAME=/.+/CMP0125/CMP0125-find_program-NEW-build/file2\.txt
+FILE_NAME_WITH_TYPE=/.+/CMP0125/CMP0125-find_program-NEW-build/file2\.txt
+RELATIVE_PATH_AND_LOCAL=relative_local
+RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local
+ABSOLUTE_PATH_AND_LOCAL=/absolute_local
+ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local
+NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125/file.txt
+NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/file.txt
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW.cmake
new file mode 100644
index 000000000..c02f23b33
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0125 NEW)
+
+include(CMP0125-find_program-Common.cmake)
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD-stderr.txt
new file mode 100644
index 000000000..a97fc0790
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD-stderr.txt
@@ -0,0 +1,14 @@
+RELATIVE_PATH=/.+/CMP0125/CMP0125-find_program-OLD-build/relative
+RELATIVE_PATH_WITH_TYPE=relative
+ABSOLUTE_PATH=/absolute
+ABSOLUTE_PATH_WITH_TYPE=/absolute
+NOTFOUND_PATH=NOTFOUND
+NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/file\.txt
+FILE_NAME=/.+/CMP0125/CMP0125-find_program-OLD-build/file2\.txt
+FILE_NAME_WITH_TYPE=file2\.txt
+RELATIVE_PATH_AND_LOCAL=/.+/CMP0125/CMP0125-find_program-OLD-build/relative
+RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local
+ABSOLUTE_PATH_AND_LOCAL=/absolute
+ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local
+NOTFOUND_PATH_AND_LOCAL=NOTFOUND
+NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/file.txt
diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD.cmake
new file mode 100644
index 000000000..6be853496
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0125 OLD)
+
+include(CMP0125-find_program-Common.cmake)
diff --git a/Tests/RunCMake/CMP0125/CMakeLists.txt b/Tests/RunCMake/CMP0125/CMakeLists.txt
new file mode 100644
index 000000000..7cabeb68b
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.20)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0125/RunCMakeTest.cmake b/Tests/RunCMake/CMP0125/RunCMakeTest.cmake
new file mode 100644
index 000000000..56d4c8635
--- /dev/null
+++ b/Tests/RunCMake/CMP0125/RunCMakeTest.cmake
@@ -0,0 +1,36 @@
+include(RunCMake)
+
+file(WRITE "${RunCMake_BINARY_DIR}/file.txt" "")
+file(CHMOD "${RunCMake_BINARY_DIR}/file.txt" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE)
+
+set(options -DRELATIVE_PATH=relative -DABSOLUTE_PATH=/absolute
+ -DRELATIVE_PATH_WITH_TYPE:PATH=relative -DABSOLUTE_PATH_WITH_TYPE:PATH=/absolute
+ -DNOTFOUND_PATH=NOTFOUND -DNOTFOUND_PATH_WITH_TYPE:PATH=NOTFOUND
+ -DFILE_NAME=file2.txt -DFILE_NAME_WITH_TYPE:PATH=file2.txt
+ -DSEARCH_NAME=file.txt "-DSEARCH_PATH=${RunCMake_BINARY_DIR}"
+ -DRELATIVE_PATH_AND_LOCAL=relative -DABSOLUTE_PATH_AND_LOCAL=/absolute
+ -DRELATIVE_PATH_WITH_TYPE_AND_LOCAL:PATH=relative -DABSOLUTE_PATH_WITH_TYPE_AND_LOCAL:PATH=/absolute
+ -DNOTFOUND_PATH_AND_LOCAL=NOTFOUND -DNOTFOUND_PATH_WITH_TYPE_AND_LOCAL:PATH=NOTFOUND
+ -DFILE_NAME=file2.txt -DFILE_NAME_WITH_TYPE:PATH=file2.txt
+ -DSEARCH_NAME=file.txt "-DSEARCH_PATH=${RunCMake_BINARY_DIR}")
+
+run_cmake_with_options(CMP0125-find_file-OLD ${options})
+run_cmake_with_options(CMP0125-find_file-NEW ${options})
+run_cmake_with_options(CMP0125-find_path-OLD ${options})
+run_cmake_with_options(CMP0125-find_path-NEW ${options})
+run_cmake_with_options(CMP0125-find_program-OLD ${options})
+run_cmake_with_options(CMP0125-find_program-NEW ${options})
+
+
+file(WRITE "${RunCMake_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}file${CMAKE_SHARED_LIBRARY_SUFFIX}" "")
+file(CHMOD "${RunCMake_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}file${CMAKE_SHARED_LIBRARY_SUFFIX}" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE)
+
+set(options -DRELATIVE_PATH=relative -DABSOLUTE_PATH=/absolute
+ -DRELATIVE_PATH_WITH_TYPE:PATH=relative -DABSOLUTE_PATH_WITH_TYPE:PATH=/absolute
+ -DNOTFOUND_PATH=NOTFOUND -DNOTFOUND_PATH_WITH_TYPE:PATH=NOTFOUND
+ -DFILE_NAME=${CMAKE_SHARED_LIBRARY_PREFIX}file2${CMAKE_SHARED_LIBRARY_SUFFIX}
+ -DFILE_NAME_WITH_TYPE:PATH=${CMAKE_SHARED_LIBRARY_PREFIX}file2${CMAKE_SHARED_LIBRARY_SUFFIX}
+ -DSEARCH_NAME=file "-DSEARCH_PATH=${RunCMake_BINARY_DIR}")
+
+run_cmake_with_options(CMP0125-find_library-OLD ${options})
+run_cmake_with_options(CMP0125-find_library-NEW ${options})
diff --git a/Tests/RunCMake/CMP0126/CMP0126-NEW.cmake b/Tests/RunCMake/CMP0126/CMP0126-NEW.cmake
new file mode 100644
index 000000000..2f8562bb9
--- /dev/null
+++ b/Tests/RunCMake/CMP0126/CMP0126-NEW.cmake
@@ -0,0 +1,28 @@
+
+# enforce policy CMP0125 to ensure predictable result of find_* commands
+cmake_policy(SET CMP0125 NEW)
+
+cmake_policy(SET CMP0126 NEW)
+
+set(VAR 1)
+set(VAR 2 CACHE STRING "")
+
+if (NOT VAR EQUAL 1)
+ message(FATAL_ERROR "normal variable does not exist anymore.")
+endif()
+
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/file.txt" "")
+set(VAR file.txt)
+set(VAR "" CACHE STRING "" FORCE)
+set_property(CACHE VAR PROPERTY TYPE UNINITIALIZED)
+
+find_file(VAR NAMES file.txt PATHS "${CMAKE_CURRENT_BINARY_DIR}")
+
+unset(VAR CACHE)
+if (NOT DEFINED VAR)
+ message(FATAL_ERROR "find_file: normal variable does not exist anymore.")
+endif()
+if (NOT VAR STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/file.txt")
+ message(FATAL_ERROR "find_file: failed to set normal variable.")
+endif()
diff --git a/Tests/RunCMake/CMP0126/CMP0126-NEW_CL.cmake b/Tests/RunCMake/CMP0126/CMP0126-NEW_CL.cmake
new file mode 100644
index 000000000..cfaa1e303
--- /dev/null
+++ b/Tests/RunCMake/CMP0126/CMP0126-NEW_CL.cmake
@@ -0,0 +1,9 @@
+
+cmake_policy(SET CMP0126 NEW)
+
+set(VAR 1)
+set(VAR 2 CACHE STRING "")
+
+if (NOT VAR EQUAL 1)
+ message(FATAL_ERROR "normal variable does not exist anymore.")
+endif()
diff --git a/Tests/RunCMake/CMP0126/CMP0126-OLD.cmake b/Tests/RunCMake/CMP0126/CMP0126-OLD.cmake
new file mode 100644
index 000000000..22a503777
--- /dev/null
+++ b/Tests/RunCMake/CMP0126/CMP0126-OLD.cmake
@@ -0,0 +1,25 @@
+
+# enforce policy CMP0125 to ensure predictable result of find_* commands
+cmake_policy(SET CMP0125 NEW)
+
+cmake_policy(SET CMP0126 OLD)
+
+set(VAR 1)
+set(VAR 2 CACHE STRING "")
+
+if (VAR EQUAL 1)
+ message(FATAL_ERROR "normal variable still exist.")
+endif()
+
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/file.txt" "")
+set(VAR file.txt)
+set(VAR "" CACHE STRING "" FORCE)
+set_property(CACHE VAR PROPERTY TYPE UNINITIALIZED)
+
+find_file(VAR NAMES file.txt PATHS "${CMAKE_CURRENT_BINARY_DIR}")
+
+unset(VAR CACHE)
+if (DEFINED VAR)
+ message(FATAL_ERROR "find_file: normal variable still exist.")
+endif()
diff --git a/Tests/RunCMake/CMP0126/CMP0126-OLD_CL.cmake b/Tests/RunCMake/CMP0126/CMP0126-OLD_CL.cmake
new file mode 100644
index 000000000..5d72a8765
--- /dev/null
+++ b/Tests/RunCMake/CMP0126/CMP0126-OLD_CL.cmake
@@ -0,0 +1,9 @@
+
+cmake_policy(SET CMP0126 OLD)
+
+set(VAR 1)
+set(VAR 2 CACHE STRING "")
+
+if (NOT VAR EQUAL 3)
+ message(FATAL_ERROR "normal variable still exist.")
+endif()
diff --git a/Tests/RunCMake/CMP0126/CMP0126-WARN-default.cmake b/Tests/RunCMake/CMP0126/CMP0126-WARN-default.cmake
new file mode 100644
index 000000000..3147fc432
--- /dev/null
+++ b/Tests/RunCMake/CMP0126/CMP0126-WARN-default.cmake
@@ -0,0 +1,3 @@
+
+set(MY_VAR 1)
+set(MY_VAR 2 CACHE STRING "")
diff --git a/Tests/RunCMake/CMP0126/CMP0126-WARN-stderr.txt b/Tests/RunCMake/CMP0126/CMP0126-WARN-stderr.txt
new file mode 100644
index 000000000..2301511e8
--- /dev/null
+++ b/Tests/RunCMake/CMP0126/CMP0126-WARN-stderr.txt
@@ -0,0 +1,10 @@
+CMake Warning \(dev\) at CMP0126-WARN.cmake:[0-9]+ \(set\):
+ Policy CMP0126 is not set: set\(CACHE\) does not remove a normal variable of
+ the same name\. Run "cmake --help-policy CMP0126" for policy details\. Use
+ the cmake_policy command to set the policy and suppress this warning\.
+
+ For compatibility with older versions of CMake, normal variable "MY_VAR"
+ will be removed from the current scope\.
+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/CMP0126/CMP0126-WARN.cmake b/Tests/RunCMake/CMP0126/CMP0126-WARN.cmake
new file mode 100644
index 000000000..111c82434
--- /dev/null
+++ b/Tests/RunCMake/CMP0126/CMP0126-WARN.cmake
@@ -0,0 +1,5 @@
+
+set(CMAKE_POLICY_WARNING_CMP0126 1)
+
+set(MY_VAR 1)
+set(MY_VAR 2 CACHE STRING "")
diff --git a/Tests/RunCMake/CMP0126/CMakeLists.txt b/Tests/RunCMake/CMP0126/CMakeLists.txt
new file mode 100644
index 000000000..7cabeb68b
--- /dev/null
+++ b/Tests/RunCMake/CMP0126/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.20)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0126/RunCMakeTest.cmake b/Tests/RunCMake/CMP0126/RunCMakeTest.cmake
new file mode 100644
index 000000000..77c38784c
--- /dev/null
+++ b/Tests/RunCMake/CMP0126/RunCMakeTest.cmake
@@ -0,0 +1,8 @@
+include(RunCMake)
+
+run_cmake(CMP0126-OLD)
+run_cmake_with_options(CMP0126-OLD_CL -DVAR=3)
+run_cmake(CMP0126-NEW)
+run_cmake_with_options(CMP0126-NEW_CL -DVAR=3)
+run_cmake(CMP0126-WARN)
+run_cmake(CMP0126-WARN-default)
diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt
new file mode 100644
index 000000000..15b56a10d
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt
@@ -0,0 +1 @@
+-- USE_FOO='ON'
diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses.cmake
new file mode 100644
index 000000000..c2951f1dc
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Parentheses.cmake
@@ -0,0 +1,7 @@
+include(CMakeDependentOption)
+
+set(A 1)
+set(B 1)
+set(C 0)
+cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF)
+message(STATUS "USE_FOO='${USE_FOO}'")
diff --git a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake
new file mode 100644
index 000000000..bbdd3e588
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake
@@ -0,0 +1,3 @@
+include(RunCMake)
+
+run_cmake_script(Parentheses)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 95f28f673..86cb849fe 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -29,6 +29,10 @@ macro(add_RunCMake_test test)
${TEST_ARGS}
-P "${CMAKE_CURRENT_SOURCE_DIR}/${Test_Dir}/RunCMakeTest.cmake"
)
+ set_tests_properties("RunCMake.${test}" PROPERTIES LABELS "CMake;run")
+ if(${test} MATCHES ^CMP)
+ set_property(TEST "RunCMake.${test}" APPEND PROPERTY LABELS "policy")
+ endif()
endmacro()
function(add_RunCMake_test_group test types)
@@ -131,6 +135,12 @@ if(CMAKE_GENERATOR MATCHES "Ninja")
endif()
add_RunCMake_test(CMP0118)
add_RunCMake_test(CMP0119 -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
+add_RunCMake_test(CMP0121)
+if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin)")
+ add_RunCMake_test(CMP0125 -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX}
+ -DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX})
+endif()
+add_RunCMake_test(CMP0126)
# The test for Policy 65 requires the use of the
# CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
@@ -160,7 +170,7 @@ if(CMAKE_GENERATOR MATCHES "Ninja")
endif()
add_RunCMake_test(Ninja)
set(NinjaMultiConfig_ARGS
- -DCYGWIN=${CYGWIN}
+ -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}
)
if(CMake_TEST_Qt5 AND Qt5Core_FOUND)
list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_Qt5=1 -DQt5Core_DIR=${Qt5Core_DIR} -DCMAKE_TEST_Qt5Core_Version=${Qt5Core_VERSION})
@@ -223,6 +233,7 @@ add_RunCMake_test(BuildDepends
if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
add_RunCMake_test(Byproducts)
endif()
+add_RunCMake_test(CMakeDependentOption)
add_RunCMake_test(CMakeRoleGlobalProperty)
add_RunCMake_test(CMakeRelease -DCMake_TEST_JQ=${CMake_TEST_JQ})
if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
@@ -262,6 +273,7 @@ add_RunCMake_test(GenEx-HOST_LINK)
add_RunCMake_test(GenEx-DEVICE_LINK)
add_RunCMake_test(GenEx-TARGET_FILE -DLINKER_SUPPORTS_PDB=${LINKER_SUPPORTS_PDB})
add_RunCMake_test(GenEx-GENEX_EVAL)
+add_RunCMake_test(GenEx-TARGET_RUNTIME_DLLS)
add_RunCMake_test(GeneratorExpression)
add_RunCMake_test(GeneratorInstance)
add_RunCMake_test(GeneratorPlatform)
@@ -276,7 +288,7 @@ add_RunCMake_test(Graphviz)
add_RunCMake_test(TargetPropertyGeneratorExpressions)
add_RunCMake_test(Languages)
add_RunCMake_test(LinkStatic)
-if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang)$")
+if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|Fujitsu|FujitsuClang)$")
add_RunCMake_test(MetaCompileFeatures)
endif()
if(MSVC)
@@ -340,7 +352,7 @@ add_RunCMake_test(export)
add_RunCMake_test(cmake_language)
add_RunCMake_test(cmake_minimum_required)
add_RunCMake_test(cmake_parse_arguments)
-add_RunCMake_test(cmake_path)
+add_RunCMake_test(cmake_path -DMSYS=${MSYS})
add_RunCMake_test(continue)
add_executable(color_warning color_warning.c)
add_executable(fake_build_command fake_build_command.c)
@@ -355,20 +367,22 @@ if(COVERAGE_COMMAND)
endif()
add_RunCMake_test(ctest_start)
add_RunCMake_test(ctest_submit)
-add_RunCMake_test(ctest_test)
+add_RunCMake_test(ctest_test
+ -DIMAGE_DIR=${CMAKE_SOURCE_DIR}/Utilities/Sphinx/static
+)
add_RunCMake_test(ctest_disabled_test)
add_RunCMake_test(ctest_skipped_test)
add_RunCMake_test(ctest_update)
add_RunCMake_test(ctest_upload)
add_RunCMake_test(ctest_fixtures)
-add_RunCMake_test(file)
-add_RunCMake_test(file-CHMOD)
+add_RunCMake_test(file -DMSYS=${MSYS})
+add_RunCMake_test(file-CHMOD -DMSYS=${MSYS})
if(HAVE_ELF_H OR CMAKE_SYSTEM_NAME STREQUAL "AIX")
add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DHAVE_ELF_H=${HAVE_ELF_H})
endif()
add_RunCMake_test(find_file)
-add_RunCMake_test(find_library -DCYGWIN=${CYGWIN})
-add_RunCMake_test(find_package)
+add_RunCMake_test(find_library -DCYGWIN=${CYGWIN} -DMSYS=${MSYS})
+add_RunCMake_test(find_package -DMSYS=${MSYS})
add_RunCMake_test(find_path)
add_RunCMake_test(find_program -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
add_RunCMake_test(foreach)
@@ -420,14 +434,21 @@ function(add_RunCMake_test_try_compile)
set(CMAKE_C_STANDARD_DEFAULT "")
endif()
endif()
+ if(CMAKE_VERSION VERSION_LESS 3.20.20210225 AND "x${CMAKE_C_COMPILER_ID}" STREQUAL "xClang")
+ # Older CMake versions do not know about Clang MSVC compatibility mode
+ # standards. Approximate the logic from Clang-C.cmake.
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0)
+ set(CMAKE_C_STANDARD_DEFAULT 17)
+ elseif(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.5.2)
+ set(CMAKE_C_STANDARD_DEFAULT 11)
+ endif()
+ endif()
if(CMAKE_VERSION VERSION_LESS 3.20.6 AND "x${CMAKE_C_COMPILER_ID}" STREQUAL "xIntelLLVM" AND "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
# Older CMake versions accidentally set the default standards to empty when
# IntelLLVM targets the MSVC ABI, thus not activating standard selection.
# Approximate the logic from IntelLLVM-{C,CXX}.cmake.
if(DEFINED CMAKE_C_STANDARD_DEFAULT AND "${CMAKE_C_STANDARD_DEFAULT}" STREQUAL "")
- # FIXME: The compiler actually defaults to C17, but
- # CMake does not yet model or detect that standard.
- set(CMAKE_C_STANDARD_DEFAULT 11)
+ set(CMAKE_C_STANDARD_DEFAULT 17)
endif()
if(DEFINED CMAKE_CXX_STANDARD_DEFAULT AND "${CMAKE_CXX_STANDARD_DEFAULT}" STREQUAL "")
set(CMAKE_CXX_STANDARD_DEFAULT 14)
@@ -443,6 +464,7 @@ function(add_RunCMake_test_try_compile)
CMAKE_CXX_STANDARD_DEFAULT
CMake_TEST_CUDA
CMake_TEST_ISPC
+ CMake_TEST_HIP
CMake_TEST_FILESYSTEM_1S
CMAKE_OBJC_STANDARD_DEFAULT
CMAKE_OBJCXX_STANDARD_DEFAULT
@@ -510,7 +532,9 @@ else()
message(STATUS "Could not find ctresalloc")
endif()
-if(NOT WIN32)
+if(NOT WIN32
+ AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS
+ )
add_RunCMake_test(SymlinkTrees)
endif ()
@@ -552,7 +576,7 @@ endif()
if(XCODE_VERSION)
add_RunCMake_test(XcodeProject -DXCODE_VERSION=${XCODE_VERSION})
- add_RunCMake_test(XcodeProject-Embed)
+ add_RunCMake_test(XcodeProject-Embed -DXCODE_VERSION=${XCODE_VERSION})
# This test can take a very long time due to lots of combinations.
# Use a long default timeout and provide an option to customize it.
@@ -584,17 +608,23 @@ set_property(TEST RunCMake.target_link_options APPEND
add_RunCMake_test(target_compile_definitions)
add_RunCMake_test(target_compile_features)
-add_RunCMake_test(target_compile_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
+add_RunCMake_test(target_compile_options
+ -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
+ -DCMAKE_C_SIMULATE_ID=${CMAKE_C_SIMULATE_ID}
+ )
add_RunCMake_test(target_include_directories)
add_RunCMake_test(target_sources)
add_RunCMake_test(CheckCompilerFlag -DCMake_TEST_CUDA=${CMake_TEST_CUDA}
-DCMake_TEST_ISPC=${CMake_TEST_ISPC}
- -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID})
+ -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID}
+ -DCMake_TEST_HIP=${CMake_TEST_HIP})
add_RunCMake_test(CheckSourceCompiles -DCMake_TEST_CUDA=${CMake_TEST_CUDA}
-DCMake_TEST_ISPC=${CMake_TEST_ISPC}
- -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID})
+ -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID}
+ -DCMake_TEST_HIP=${CMake_TEST_HIP})
add_RunCMake_test(CheckSourceRuns -DCMake_TEST_CUDA=${CMake_TEST_CUDA}
- -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID})
+ -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID}
+ -DCMake_TEST_HIP=${CMake_TEST_HIP})
set_property(TEST RunCMake.CheckCompilerFlag
RunCMake.CheckSourceCompiles
RunCMake.CheckSourceRuns
@@ -602,19 +632,26 @@ set_property(TEST RunCMake.CheckCompilerFlag
set_property(TEST RunCMake.CheckSourceCompiles
RunCMake.CheckCompilerFlag
APPEND PROPERTY LABELS "ISPC")
+set_property(TEST RunCMake.CheckCompilerFlag
+ RunCMake.CheckSourceCompiles
+ RunCMake.CheckSourceRuns
+ APPEND PROPERTY LABELS "HIP")
add_RunCMake_test(CheckModules)
add_RunCMake_test(CheckIPOSupported)
if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin)"
AND (CMAKE_C_COMPILER_ID MATCHES "Clang|GNU" OR CMAKE_Fortran_COMPILER_ID MATCHES "GNU"))
add_RunCMake_test(CheckLinkerFlag -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
-DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID}
- -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
+ -DCMake_TEST_CUDA=${CMake_TEST_CUDA}
+ -DCMake_TEST_HIP=${CMake_TEST_HIP})
set_property(TEST RunCMake.CheckLinkerFlag APPEND PROPERTY LABELS "CUDA")
+ set_property(TEST RunCMake.CheckLinkerFlag APPEND PROPERTY LABELS "HIP")
endif()
add_executable(pseudo_llvm-rc pseudo_llvm-rc.c)
-add_RunCMake_test(CommandLine -DLLVM_RC=$<TARGET_FILE:pseudo_llvm-rc> -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCYGWIN=${CYGWIN} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE})
+add_RunCMake_test(CommandLine -DLLVM_RC=$<TARGET_FILE:pseudo_llvm-rc> -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
+ -DCYGWIN=${CYGWIN} -DMSYS=${MSYS} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE})
add_RunCMake_test(CommandLineTar)
if(CMAKE_PLATFORM_NO_VERSIONED_SONAME OR (NOT CMAKE_SHARED_LIBRARY_SONAME_FLAG AND NOT CMAKE_SHARED_LIBRARY_SONAME_C_FLAG))
@@ -623,7 +660,7 @@ else()
set(NO_NAMELINK 0)
endif()
-add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN}
+add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}
-DCMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN=${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN}
-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-DCMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG=${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG}
@@ -712,6 +749,9 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
if(DEFINED CMake_TEST_CUDA)
list(APPEND CompilerLauncher_ARGS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
endif()
+ if(DEFINED CMake_TEST_HIP)
+ list(APPEND CompilerLauncher_ARGS -DCMake_TEST_HIP=${CMake_TEST_HIP})
+ endif()
if(DEFINED CMake_TEST_ISPC)
list(APPEND CompilerLauncher_ARGS -DCMake_TEST_ISPC=${CMake_TEST_ISPC})
endif()
@@ -720,12 +760,14 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
endif()
if (APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
list(APPEND CompilerLauncher_ARGS -DCMake_TEST_OBJC=1)
+ list(APPEND LinkerLauncher_ARGS -DCMake_TEST_OBJC=1)
endif()
add_RunCMake_test(CompilerLauncher)
set_property(TEST RunCMake.CompilerLauncher APPEND
- PROPERTY LABELS "CUDA;ISPC")
+ PROPERTY LABELS "CUDA;HIP;ISPC")
add_RunCMake_test(ctest_labels_for_subprojects)
add_RunCMake_test(CompilerArgs)
+ add_RunCMake_test(LinkerLauncher)
endif()
set(cpack_tests
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-result.txt b/Tests/RunCMake/CMakePresets/ConditionFuture-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-result.txt
+++ b/Tests/RunCMake/CMakePresets/ConditionFuture-result.txt
diff --git a/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt b/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt
new file mode 100644
index 000000000..ea5f47f65
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ConditionFuture: File version must be 3 or higher for condition support$
diff --git a/Tests/RunCMake/CMakePresets/ConditionFuture.json.in b/Tests/RunCMake/CMakePresets/ConditionFuture.json.in
new file mode 100644
index 000000000..9d4798b58
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ConditionFuture.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "ConditionFuture",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "condition": true
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/Conditions.json.in b/Tests/RunCMake/CMakePresets/Conditions.json.in
new file mode 100644
index 000000000..9c0c6bddf
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/Conditions.json.in
@@ -0,0 +1,406 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "Base",
+ "hidden": true,
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "SimpleTrue",
+ "inherits": "Base",
+ "condition": true
+ },
+ {
+ "name": "SimpleFalse",
+ "inherits": "Base",
+ "condition": false
+ },
+ {
+ "name": "Null",
+ "inherits": "Base",
+ "condition": null
+ },
+ {
+ "name": "ConstTrue",
+ "inherits": "Base",
+ "condition": {
+ "type": "const",
+ "value": true
+ }
+ },
+ {
+ "name": "ConstFalse",
+ "inherits": "Base",
+ "condition": {
+ "type": "const",
+ "value": false
+ }
+ },
+ {
+ "name": "EqualsTrue",
+ "inherits": "Base",
+ "condition": {
+ "type": "equals",
+ "lhs": "abc",
+ "rhs": "abc"
+ }
+ },
+ {
+ "name": "EqualsFalse",
+ "inherits": "Base",
+ "condition": {
+ "type": "equals",
+ "lhs": "abc",
+ "rhs": "abcd"
+ }
+ },
+ {
+ "name": "EqualsMacroLeft",
+ "inherits": "Base",
+ "condition": {
+ "type": "equals",
+ "lhs": "${presetName}",
+ "rhs": "EqualsMacroLeft"
+ }
+ },
+ {
+ "name": "EqualsMacroRight",
+ "inherits": "Base",
+ "condition": {
+ "type": "equals",
+ "lhs": "EqualsMacroRight",
+ "rhs": "${presetName}"
+ }
+ },
+ {
+ "name": "NotEqualsTrue",
+ "inherits": "Base",
+ "condition": {
+ "type": "notEquals",
+ "lhs": "abc",
+ "rhs": "abcd"
+ }
+ },
+ {
+ "name": "NotEqualsFalse",
+ "inherits": "Base",
+ "condition": {
+ "type": "notEquals",
+ "lhs": "abc",
+ "rhs": "abc"
+ }
+ },
+ {
+ "name": "InListTrue",
+ "inherits": "Base",
+ "condition": {
+ "type": "inList",
+ "string": "b",
+ "list": [
+ "a",
+ "b",
+ "c"
+ ]
+ }
+ },
+ {
+ "name": "InListFalse",
+ "inherits": "Base",
+ "condition": {
+ "type": "inList",
+ "string": "d",
+ "list": [
+ "a",
+ "b",
+ "c"
+ ]
+ }
+ },
+ {
+ "name": "InListMacroString",
+ "inherits": "Base",
+ "condition": {
+ "type": "inList",
+ "string": "${presetName}",
+ "list": [
+ "InListMacroString",
+ "AnotherString"
+ ]
+ }
+ },
+ {
+ "name": "InListMacroList",
+ "inherits": "Base",
+ "condition": {
+ "type": "inList",
+ "string": "InListMacroList",
+ "list": [
+ "${presetName}",
+ "AnotherString"
+ ]
+ }
+ },
+ {
+ "name": "InListShortCircuit",
+ "inherits": "Base",
+ "condition": {
+ "type": "inList",
+ "string": "a",
+ "list": [
+ "a",
+ "${invalidMacro}"
+ ]
+ }
+ },
+ {
+ "name": "NotInListTrue",
+ "inherits": "Base",
+ "condition": {
+ "type": "notInList",
+ "string": "d",
+ "list": [
+ "a",
+ "b",
+ "c"
+ ]
+ }
+ },
+ {
+ "name": "NotInListFalse",
+ "inherits": "Base",
+ "condition": {
+ "type": "notInList",
+ "string": "a",
+ "list": [
+ "a",
+ "b",
+ "c"
+ ]
+ }
+ },
+ {
+ "name": "MatchesTrue",
+ "inherits": "Base",
+ "condition": {
+ "type": "matches",
+ "string": "aaa",
+ "regex": "^a*$"
+ }
+ },
+ {
+ "name": "MatchesFalse",
+ "inherits": "Base",
+ "condition": {
+ "type": "matches",
+ "string": "aab",
+ "regex": "^a*$"
+ }
+ },
+ {
+ "name": "MatchesMacroString",
+ "inherits": "Base",
+ "condition": {
+ "type": "matches",
+ "string": "${presetName}",
+ "regex": "^Matches"
+ }
+ },
+ {
+ "name": "MatchesMacroRegex",
+ "inherits": "Base",
+ "condition": {
+ "type": "matches",
+ "string": "stuff",
+ "regex": "$env{CONDITION_REGEX}"
+ },
+ "environment": {
+ "CONDITION_REGEX": "^stuf*$"
+ }
+ },
+ {
+ "name": "NotMatchesTrue",
+ "inherits": "Base",
+ "condition": {
+ "type": "notMatches",
+ "string": "aab",
+ "regex": "^a*$"
+ }
+ },
+ {
+ "name": "NotMatchesFalse",
+ "inherits": "Base",
+ "condition": {
+ "type": "notMatches",
+ "string": "aaa",
+ "regex": "^a*$"
+ }
+ },
+ {
+ "name": "AnyOfTrue1",
+ "inherits": "Base",
+ "condition": {
+ "type": "anyOf",
+ "conditions": [
+ true,
+ false
+ ]
+ }
+ },
+ {
+ "name": "AnyOfTrue2",
+ "inherits": "Base",
+ "condition": {
+ "type": "anyOf",
+ "conditions": [
+ false,
+ true
+ ]
+ }
+ },
+ {
+ "name": "AnyOfFalse",
+ "inherits": "Base",
+ "condition": {
+ "type": "anyOf",
+ "conditions": [
+ false,
+ {
+ "type": "equals",
+ "lhs": "abc",
+ "rhs": "abcd"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AnyOfShortCircuit",
+ "inherits": "Base",
+ "condition": {
+ "type": "anyOf",
+ "conditions": [
+ true,
+ {
+ "type": "equals",
+ "lhs": "${invalidMacro}",
+ "rhs": ""
+ }
+ ]
+ }
+ },
+ {
+ "name": "AnyOfEmpty",
+ "inherits": "Base",
+ "condition": {
+ "type": "anyOf",
+ "conditions": []
+ }
+ },
+ {
+ "name": "AllOfTrue",
+ "inherits": "Base",
+ "condition": {
+ "type": "allOf",
+ "conditions": [
+ true,
+ {
+ "type": "equals",
+ "lhs": "abc",
+ "rhs": "abc"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AllOfFalse1",
+ "inherits": "Base",
+ "condition": {
+ "type": "allOf",
+ "conditions": [
+ false,
+ true
+ ]
+ }
+ },
+ {
+ "name": "AllOfFalse2",
+ "inherits": "Base",
+ "condition": {
+ "type": "allOf",
+ "conditions": [
+ true,
+ false
+ ]
+ }
+ },
+ {
+ "name": "AllOfShortCircuit",
+ "inherits": "Base",
+ "condition": {
+ "type": "allOf",
+ "conditions": [
+ false,
+ {
+ "type": "equals",
+ "lhs": "${invalidMacro}",
+ "rhs": ""
+ }
+ ]
+ }
+ },
+ {
+ "name": "AllOfEmpty",
+ "inherits": "Base",
+ "condition": {
+ "type": "allOf",
+ "conditions": []
+ }
+ },
+ {
+ "name": "NotTrue",
+ "inherits": "Base",
+ "condition": {
+ "type": "not",
+ "condition": true
+ }
+ },
+ {
+ "name": "NotFalse",
+ "inherits": "Base",
+ "condition": {
+ "type": "not",
+ "condition": false
+ }
+ },
+ {
+ "name": "InheritanceBase",
+ "inherits": "Base",
+ "hidden": true,
+ "condition": {
+ "type": "equals",
+ "lhs": "${presetName}",
+ "rhs": "InheritanceChildTrue"
+ }
+ },
+ {
+ "name": "InheritanceChildTrue",
+ "inherits": "InheritanceBase"
+ },
+ {
+ "name": "InheritanceChildFalse",
+ "inherits": "InheritanceBase"
+ },
+ {
+ "name": "InheritanceNull",
+ "inherits": "Null"
+ },
+ {
+ "name": "InheritanceNullFalse",
+ "inherits": [
+ "Null",
+ "SimpleFalse"
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-result.txt b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-result.txt
+++ b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-result.txt
diff --git a/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt
new file mode 100644
index 000000000..36123bdac
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField: File version must be 3 or higher for installDir preset support.$
diff --git a/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField.json.in b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField.json.in
new file mode 100644
index 000000000..2e5f7d519
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "FuturePresetInstallDirField",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "installDir": "${sourceDir}/install"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-result.txt b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-result.txt
+++ b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-result.txt
diff --git a/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt
new file mode 100644
index 000000000..9382423a3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/FuturePresetToolchainField: File version must be 3 or higher for toolchainFile preset support.$
diff --git a/Tests/RunCMake/CMakePresets/FuturePresetToolchainField.json.in b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField.json.in
new file mode 100644
index 000000000..646ee0f08
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "FuturePresetToolchainField",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "toolchainFile": "${sourceDir}/toolchain.cmake"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/GoodInstall.json.in b/Tests/RunCMake/CMakePresets/GoodInstall.json.in
new file mode 100644
index 000000000..6287c6580
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInstall.json.in
@@ -0,0 +1,30 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "GoodInstallDefault",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}",
+ "installDir": "${sourceDir}/build/install_dir1"
+ },
+ {
+ "name": "GoodInstallInherit",
+ "inherits": "GoodInstallDefault",
+ "cacheVariables": {
+ "CMAKE_INSTALL_PREFIX": {
+ "type": "PATH",
+ "value": "${sourceDir}/build/bad_path"
+ }
+ }
+ },
+ {
+ "name": "GoodInstallOverride",
+ "inherits": "GoodInstallInherit",
+ "installDir": "${sourceDir}/build/install_dir2"
+ },
+ {
+ "name": "GoodInstallCommandLine",
+ "inherits": "GoodInstallOverride"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/GoodInstallCommandLine.cmake b/Tests/RunCMake/CMakePresets/GoodInstallCommandLine.cmake
new file mode 100644
index 000000000..a4f61786e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInstallCommandLine.cmake
@@ -0,0 +1,3 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_variable("CMAKE_INSTALL_PREFIX" "PATH" "${RunCMake_SOURCE_DIR}/path/passed/on/command_line")
diff --git a/Tests/RunCMake/CMakePresets/GoodInstallDefault.cmake b/Tests/RunCMake/CMakePresets/GoodInstallDefault.cmake
new file mode 100644
index 000000000..656fda0b9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInstallDefault.cmake
@@ -0,0 +1,3 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_variable("CMAKE_INSTALL_PREFIX" "PATH" "${CMAKE_SOURCE_DIR}/build/install_dir1")
diff --git a/Tests/RunCMake/CMakePresets/GoodInstallInherit.cmake b/Tests/RunCMake/CMakePresets/GoodInstallInherit.cmake
new file mode 100644
index 000000000..656fda0b9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInstallInherit.cmake
@@ -0,0 +1,3 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_variable("CMAKE_INSTALL_PREFIX" "PATH" "${CMAKE_SOURCE_DIR}/build/install_dir1")
diff --git a/Tests/RunCMake/CMakePresets/GoodInstallOverride.cmake b/Tests/RunCMake/CMakePresets/GoodInstallOverride.cmake
new file mode 100644
index 000000000..3d12b07ed
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInstallOverride.cmake
@@ -0,0 +1,3 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_variable("CMAKE_INSTALL_PREFIX" "PATH" "${CMAKE_SOURCE_DIR}/build/install_dir2")
diff --git a/Tests/RunCMake/CMakePresets/GoodToolchain.json.in b/Tests/RunCMake/CMakePresets/GoodToolchain.json.in
new file mode 100644
index 000000000..69dafcf11
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodToolchain.json.in
@@ -0,0 +1,30 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "GoodToolchainDefault",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}",
+ "toolchainFile": "${sourceDir}/toolchain.cmake"
+ },
+ {
+ "name": "GoodToolchainInherit",
+ "inherits": "GoodToolchainDefault",
+ "cacheVariables": {
+ "CMAKE_TOOLCHAIN_FILE": {
+ "type": "FILEPATH",
+ "value": "${sourceDir}/toolchain_bad.cmake"
+ }
+ }
+ },
+ {
+ "name": "GoodToolchainOverride",
+ "inherits": "GoodToolchainInherit",
+ "toolchainFile": "override_toolchain.cmake"
+ },
+ {
+ "name": "GoodToolchainCommandLine",
+ "inherits": "GoodToolchainOverride"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/GoodToolchainCommandLine.cmake b/Tests/RunCMake/CMakePresets/GoodToolchainCommandLine.cmake
new file mode 100644
index 000000000..c37421c39
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodToolchainCommandLine.cmake
@@ -0,0 +1,3 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_variable("CMAKE_TOOLCHAIN_FILE" "FILEPATH" "${CMAKE_SOURCE_DIR}/cmd_line_toolchain.cmake")
diff --git a/Tests/RunCMake/CMakePresets/GoodToolchainDefault.cmake b/Tests/RunCMake/CMakePresets/GoodToolchainDefault.cmake
new file mode 100644
index 000000000..53c938b47
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodToolchainDefault.cmake
@@ -0,0 +1,3 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_variable("CMAKE_TOOLCHAIN_FILE" "FILEPATH" "${CMAKE_SOURCE_DIR}/toolchain.cmake")
diff --git a/Tests/RunCMake/CMakePresets/GoodToolchainInherit.cmake b/Tests/RunCMake/CMakePresets/GoodToolchainInherit.cmake
new file mode 100644
index 000000000..53c938b47
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodToolchainInherit.cmake
@@ -0,0 +1,3 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_variable("CMAKE_TOOLCHAIN_FILE" "FILEPATH" "${CMAKE_SOURCE_DIR}/toolchain.cmake")
diff --git a/Tests/RunCMake/CMakePresets/GoodToolchainOverride.cmake b/Tests/RunCMake/CMakePresets/GoodToolchainOverride.cmake
new file mode 100644
index 000000000..558134ca2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodToolchainOverride.cmake
@@ -0,0 +1,3 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_variable("CMAKE_TOOLCHAIN_FILE" "FILEPATH" "${CMAKE_SOURCE_DIR}/override_toolchain.cmake")
diff --git a/Tests/RunCMake/CMakePresets/HostSystemName.cmake b/Tests/RunCMake/CMakePresets/HostSystemName.cmake
new file mode 100644
index 000000000..dc0998aa3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/HostSystemName.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(TEST_HOST_SYSTEM_NAME "" "${CMAKE_HOST_SYSTEM_NAME}")
diff --git a/Tests/RunCMake/CMakePresets/HostSystemName.json.in b/Tests/RunCMake/CMakePresets/HostSystemName.json.in
new file mode 100644
index 000000000..7fcd8c836
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/HostSystemName.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "HostSystemName",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "TEST_HOST_SYSTEM_NAME": "${hostSystemName}"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-result.txt b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-result.txt
+++ b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-result.txt
diff --git a/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt
new file mode 100644
index 000000000..7f4bb9a24
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/HostSystemNameFuture: Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/HostSystemNameFuture.json.in b/Tests/RunCMake/CMakePresets/HostSystemNameFuture.json.in
new file mode 100644
index 000000000..7a2f0aa1f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/HostSystemNameFuture.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "HostSystemNameFuture",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "TEST_HOST_SYSTEM_NAME": "${hostSystemName}"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-result.txt b/Tests/RunCMake/CMakePresets/InvalidRegex-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-result.txt
+++ b/Tests/RunCMake/CMakePresets/InvalidRegex-result.txt
diff --git a/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt
new file mode 100644
index 000000000..5b500e44e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidRegex: Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/InvalidRegex.json.in b/Tests/RunCMake/CMakePresets/InvalidRegex.json.in
new file mode 100644
index 000000000..69114d2e3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidRegex.json.in
@@ -0,0 +1,15 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "InvalidRegex",
+ "binaryDir": "${sourceDir}/build",
+ "generator": "@RunCMake_GENERATOR@",
+ "condition": {
+ "type": "matches",
+ "string": "a",
+ "regex": "+"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt b/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt
new file mode 100644
index 000000000..91e001707
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt
@@ -0,0 +1,26 @@
+Available configure presets:
+
+ "SimpleTrue"
+ "Null"
+ "ConstTrue"
+ "EqualsTrue"
+ "EqualsMacroLeft"
+ "EqualsMacroRight"
+ "NotEqualsTrue"
+ "InListTrue"
+ "InListMacroString"
+ "InListMacroList"
+ "InListShortCircuit"
+ "NotInListTrue"
+ "MatchesTrue"
+ "MatchesMacroString"
+ "MatchesMacroRegex"
+ "NotMatchesTrue"
+ "AnyOfTrue1"
+ "AnyOfTrue2"
+ "AnyOfShortCircuit"
+ "AllOfTrue"
+ "AllOfEmpty"
+ "NotFalse"
+ "InheritanceChildTrue"
+ "InheritanceNull"$
diff --git a/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
index 60d6adbd9..97eedae7c 100644
--- a/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
@@ -1,6 +1,7 @@
^Not searching for unused variables given on the command line\.
Available configure presets:
- "zzzzzz" - Sleepy
- "aaaaaaaa" - Screaming
- "mmmmmm"$
+ "zzzzzz" - Sleepy
+ "aaaaaaaa" - Screaming
+ "mmmmmm"
+ "no-generator"$
diff --git a/Tests/RunCMake/CMakePresets/ListPresets.json.in b/Tests/RunCMake/CMakePresets/ListPresets.json.in
index 2ef3797da..160098c53 100644
--- a/Tests/RunCMake/CMakePresets/ListPresets.json.in
+++ b/Tests/RunCMake/CMakePresets/ListPresets.json.in
@@ -1,5 +1,5 @@
{
- "version": 1,
+ "version": 3,
"configurePresets": [
{
"name": "zzzzzz",
@@ -19,6 +19,9 @@
"binaryDir": "${sourceDir}/build/mmmmmm"
},
{
+ "name": "no-generator"
+ },
+ {
"name": "invalid-generator",
"generator": "Invalid Generator",
"binaryDir": "${sourceDir}/build/invalid"
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
index 60d6adbd9..97eedae7c 100644
--- a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
@@ -1,6 +1,7 @@
^Not searching for unused variables given on the command line\.
Available configure presets:
- "zzzzzz" - Sleepy
- "aaaaaaaa" - Screaming
- "mmmmmm"$
+ "zzzzzz" - Sleepy
+ "aaaaaaaa" - Screaming
+ "mmmmmm"
+ "no-generator"$
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
index 60d6adbd9..97eedae7c 100644
--- a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
@@ -1,6 +1,7 @@
^Not searching for unused variables given on the command line\.
Available configure presets:
- "zzzzzz" - Sleepy
- "aaaaaaaa" - Screaming
- "mmmmmm"$
+ "zzzzzz" - Sleepy
+ "aaaaaaaa" - Screaming
+ "mmmmmm"
+ "no-generator"$
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
index 60d6adbd9..97eedae7c 100644
--- a/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
@@ -1,6 +1,7 @@
^Not searching for unused variables given on the command line\.
Available configure presets:
- "zzzzzz" - Sleepy
- "aaaaaaaa" - Screaming
- "mmmmmm"$
+ "zzzzzz" - Sleepy
+ "aaaaaaaa" - Screaming
+ "mmmmmm"
+ "no-generator"$
diff --git a/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.cmake b/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.cmake
new file mode 100644
index 000000000..49e7a2550
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
diff --git a/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.json.in b/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.json.in
new file mode 100644
index 000000000..ee17a222c
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.json.in
@@ -0,0 +1,9 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "OptionalBinaryDirField",
+ "generator": "@RunCMake_GENERATOR@"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/OptionalGeneratorField.cmake b/Tests/RunCMake/CMakePresets/OptionalGeneratorField.cmake
new file mode 100644
index 000000000..4319e7216
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/OptionalGeneratorField.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_GENERATOR "" "${RunCMake_GENERATOR}")
diff --git a/Tests/RunCMake/CMakePresets/OptionalGeneratorField.json.in b/Tests/RunCMake/CMakePresets/OptionalGeneratorField.json.in
new file mode 100644
index 000000000..920d05632
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/OptionalGeneratorField.json.in
@@ -0,0 +1,9 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "OptionalGeneratorField",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
index dfc56eeb7..3b9806ab7 100644
--- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
@@ -11,14 +11,23 @@ set(RunCMake-check-file check.cmake)
include("${RunCMake_SOURCE_DIR}/validate_schema.cmake")
+function(reset_cmake_presets_directory name)
+ set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}")
+ file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}")
+endfunction()
+
function(run_cmake_presets name)
set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}")
set(_source_arg "${RunCMake_TEST_SOURCE_DIR}")
if(CMakePresets_SOURCE_ARG)
set(_source_arg "${CMakePresets_SOURCE_ARG}")
endif()
- file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}")
- file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}")
+
+ if(NOT RunCMake_TEST_SOURCE_DIR_NO_CLEAN)
+ file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}")
+ endif()
configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY)
if(NOT CMakePresets_FILE)
@@ -94,6 +103,8 @@ run_cmake_presets(InvalidVariableValue)
run_cmake_presets(ExtraRootField)
run_cmake_presets(ExtraPresetField)
run_cmake_presets(ExtraVariableField)
+run_cmake_presets(FuturePresetInstallDirField)
+run_cmake_presets(FuturePresetToolchainField)
run_cmake_presets(InvalidPresetVendor)
set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
run_cmake_presets(DuplicatePresets)
@@ -116,7 +127,10 @@ run_cmake_presets(NoSuchMacro)
run_cmake_presets(EnvCycle)
run_cmake_presets(EmptyEnv)
run_cmake_presets(EmptyPenv)
+run_cmake_presets(InvalidRegex)
set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
+run_cmake_presets(ConditionFuture)
+run_cmake_presets(SubConditionNull)
# Test cmakeMinimumRequired field
run_cmake_presets(MinimumRequiredInvalid)
@@ -181,6 +195,35 @@ run_cmake_presets(GoodInheritanceMulti)
run_cmake_presets(GoodInheritanceMultiSecond)
run_cmake_presets(GoodInheritanceMacro)
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/GoodInstall.json.in")
+run_cmake_presets(GoodInstallDefault)
+run_cmake_presets(GoodInstallInherit)
+run_cmake_presets(GoodInstallOverride)
+run_cmake_presets(GoodInstallCommandLine "--install-prefix=${RunCMake_SOURCE_DIR}/path/passed/on/command_line")
+
+set(RunCMake_TEST_SOURCE_DIR_NO_CLEAN 1)
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/GoodToolchain.json.in")
+
+reset_cmake_presets_directory(GoodToolchainInherit)
+file(WRITE "${RunCMake_BINARY_DIR}/GoodToolchainDefault/toolchain.cmake" "")
+run_cmake_presets(GoodToolchainDefault)
+
+reset_cmake_presets_directory(GoodToolchainInherit)
+file(WRITE "${RunCMake_BINARY_DIR}/GoodToolchainInherit/toolchain.cmake" "")
+run_cmake_presets(GoodToolchainInherit)
+
+reset_cmake_presets_directory(GoodToolchainOverride)
+file(WRITE "${RunCMake_BINARY_DIR}/GoodToolchainOverride/override_toolchain.cmake" "")
+run_cmake_presets(GoodToolchainOverride)
+
+reset_cmake_presets_directory(GoodToolchainCommandLine)
+file(WRITE "${RunCMake_BINARY_DIR}/GoodToolchainCommandLine/cmd_line_toolchain.cmake" "")
+run_cmake_presets(GoodToolchainCommandLine "--toolchain=${RunCMake_BINARY_DIR}/GoodToolchainCommandLine/cmd_line_toolchain.cmake")
+
+unset(RunCMake_TEST_SOURCE_DIR_NO_CLEAN)
+
+
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/CMakePresets.json.in")
# Test bad preset arguments
run_cmake_presets(VendorMacro)
run_cmake_presets(InvalidGenerator)
@@ -253,9 +296,29 @@ set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Debug.json.in")
run_cmake_presets(NoDebug)
run_cmake_presets(Debug)
+# Test ${hostSystemName} macro
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/HostSystemName.json.in")
+run_cmake_presets(HostSystemName)
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/HostSystemNameFuture.json.in")
+run_cmake_presets(HostSystemNameFuture)
+
+# Test conditions
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Conditions.json.in")
+run_cmake_presets(ListConditions --list-presets)
+run_cmake_presets(SimpleTrue)
+run_cmake_presets(SimpleFalse)
+unset(CMakePresets_FILE)
+
+# Test optional generator and buildDir fields
+run_cmake_presets(OptionalBinaryDirField -B "${RunCMake_BINARY_DIR}/OptionalBinaryDirField/build")
+run_cmake_presets(OptionalGeneratorField -G "${RunCMake_GENERATOR}")
+
# Test the example from the documentation
file(READ "${RunCMake_SOURCE_DIR}/../../../Help/manual/presets/example.json" _example)
string(REPLACE "\"generator\": \"Ninja\"" "\"generator\": \"@RunCMake_GENERATOR@\"" _example "${_example}")
+if(CMAKE_HOST_WIN32)
+ string(REPLACE [["PATH": "$env{HOME}/ninja/bin:$penv{PATH}"]] [["PATH": "$env{HOME}/ninja/bin;$penv{PATH}"]] _example "${_example}")
+endif()
file(WRITE "${RunCMake_BINARY_DIR}/example.json.in" "${_example}")
set(CMakePresets_FILE "${RunCMake_BINARY_DIR}/example.json.in")
run_cmake_presets(DocumentationExample --preset=default)
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-result.txt b/Tests/RunCMake/CMakePresets/SimpleFalse-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-result.txt
+++ b/Tests/RunCMake/CMakePresets/SimpleFalse-result.txt
diff --git a/Tests/RunCMake/CMakePresets/SimpleFalse-stderr.txt b/Tests/RunCMake/CMakePresets/SimpleFalse-stderr.txt
new file mode 100644
index 000000000..6a9a7dea2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/SimpleFalse-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: Could not use disabled preset "SimpleFalse"$
diff --git a/Tests/RunCMake/TransformDepfile/empty.tlog.txt b/Tests/RunCMake/CMakePresets/SimpleTrue.cmake
index e69de29bb..e69de29bb 100644
--- a/Tests/RunCMake/TransformDepfile/empty.tlog.txt
+++ b/Tests/RunCMake/CMakePresets/SimpleTrue.cmake
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-result.txt b/Tests/RunCMake/CMakePresets/SubConditionNull-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-result.txt
+++ b/Tests/RunCMake/CMakePresets/SubConditionNull-result.txt
diff --git a/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt b/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt
new file mode 100644
index 000000000..42b74d617
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/SubConditionNull: Invalid preset condition$
diff --git a/Tests/RunCMake/CMakePresets/SubConditionNull.json.in b/Tests/RunCMake/CMakePresets/SubConditionNull.json.in
new file mode 100644
index 000000000..eed3da689
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/SubConditionNull.json.in
@@ -0,0 +1,14 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "SubConditionNull",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "condition": {
+ "type": "not",
+ "condition": null
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-result.txt b/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-result.txt
+++ b/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-result.txt
diff --git a/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-stderr.txt
new file mode 100644
index 000000000..c35f5d7d8
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Cannot use disabled build preset in [^
+]*/Tests/RunCMake/CMakePresetsBuild/Condition: "disabled"$
diff --git a/Tests/RunCMake/TransformDepfile/noexist.tlog.txt b/Tests/RunCMake/CMakePresetsBuild/Condition.cmake
index e69de29bb..e69de29bb 100644
--- a/Tests/RunCMake/TransformDepfile/noexist.tlog.txt
+++ b/Tests/RunCMake/CMakePresetsBuild/Condition.cmake
diff --git a/Tests/RunCMake/CMakePresetsBuild/Condition.json.in b/Tests/RunCMake/CMakePresetsBuild/Condition.json.in
new file mode 100644
index 000000000..aaee96a8d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Condition.json.in
@@ -0,0 +1,22 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "enabled",
+ "configurePreset": "default",
+ "condition": true
+ },
+ {
+ "name": "disabled",
+ "configurePreset": "default",
+ "condition": false
+ }
+ ]
+}
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-result.txt b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-result.txt
+++ b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-result.txt
diff --git a/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt
new file mode 100644
index 000000000..f08f4c11b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsBuild/ConditionFuture: File version must be 3 or higher for condition support$
diff --git a/Tests/RunCMake/CMakePresetsBuild/ConditionFuture.json.in b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture.json.in
new file mode 100644
index 000000000..2f3f7d851
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture.json.in
@@ -0,0 +1,17 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "conditionFuture",
+ "configurePreset": "default",
+ "condition": true
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt b/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt
index 4d30707d4..2d362d4f5 100644
--- a/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt
+++ b/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt
@@ -1,5 +1,6 @@
-Available build presets:
+^Available build presets:
"build-default" - build-default displayName
"empty"
"display" - display displayName
+ "true"$
diff --git a/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in b/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in
index 3f5e02c25..26504d309 100644
--- a/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in
+++ b/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in
@@ -1,5 +1,5 @@
{
- "version": 2,
+ "version": 3,
"configurePresets": [
{
"name": "default",
@@ -26,6 +26,16 @@
{
"name": "hidden",
"hidden": true
+ },
+ {
+ "name": "true",
+ "inherits": "build-default",
+ "condition": true
+ },
+ {
+ "name": "false",
+ "inherits": "build-default",
+ "condition": false
}
]
}
diff --git a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake
index a05ad9ffd..b37c7709a 100644
--- a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake
@@ -72,6 +72,7 @@ endif()
run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject;singleTarget")
run_cmake_build_presets(InvalidConfigurePreset "default" "badConfigurePreset")
+run_cmake_build_presets(Condition "default" "enabled;disabled")
set(CMakePresetsBuild_BUILD_ONLY 1)
run_cmake_build_presets(ListPresets "x" "x" "--list-presets")
@@ -80,5 +81,6 @@ run_cmake_build_presets(Invalid "x" "hidden;vendorMacro")
set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
run_cmake_build_presets(PresetsUnsupported "x" "x")
+run_cmake_build_presets(ConditionFuture "x" "conditionFuture")
set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
set(CMakePresetsBuild_BUILD_ONLY 0)
diff --git a/Tests/RunCMake/CMakePresetsTest/Condition.json.in b/Tests/RunCMake/CMakePresetsTest/Condition.json.in
new file mode 100644
index 000000000..0baf17613
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Condition.json.in
@@ -0,0 +1,22 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "enabled",
+ "configurePreset": "default",
+ "condition": true
+ },
+ {
+ "name": "disabled",
+ "configurePreset": "default",
+ "condition": false
+ }
+ ]
+}
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-result.txt b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-result.txt
+++ b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-result.txt
diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt
new file mode 100644
index 000000000..b814bbb94
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsTest/ConditionFuture: File version must be 3 or higher for condition support$
diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionFuture.json.in b/Tests/RunCMake/CMakePresetsTest/ConditionFuture.json.in
new file mode 100644
index 000000000..4b9f33f66
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/ConditionFuture.json.in
@@ -0,0 +1,17 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "conditionFuture",
+ "configurePreset": "default",
+ "condition": true
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionListPresets-test-x-stdout.txt b/Tests/RunCMake/CMakePresetsTest/ConditionListPresets-test-x-stdout.txt
new file mode 100644
index 000000000..11918e519
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/ConditionListPresets-test-x-stdout.txt
@@ -0,0 +1,3 @@
+^Available test presets:
+
+ "enabled"$
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-result.txt b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-result.txt
+++ b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-result.txt
diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-stderr.txt b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-stderr.txt
new file mode 100644
index 000000000..5db3b77e6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Cannot use disabled test preset in [^
+]*/Tests/RunCMake/CMakePresetsTest/ConditionRunTests: "disabled"$
diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionRunTests.cmake b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests.cmake
new file mode 100644
index 000000000..b29161edf
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests.cmake
@@ -0,0 +1,2 @@
+enable_testing()
+add_test(true ${CMAKE_COMMAND} -E true)
diff --git a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
index c93dff36f..70d25d4ec 100644
--- a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
@@ -90,6 +90,12 @@ run_cmake_test_presets(InvalidConfigurePreset "default" "" "badConfigurePreset")
set(CMakePresetsTest_NO_CONFIGURE 1)
set(CMakePresetsTest_FILE "${RunCMake_SOURCE_DIR}/Good.json.in")
run_cmake_test_presets(ListPresets "" "" "x" "--list-presets")
+
+set(CMakePresetsTest_FILE "${RunCMake_SOURCE_DIR}/Condition.json.in")
+run_cmake_test_presets(ConditionListPresets "" "" "x" "--list-presets")
+unset(CMakePresetsTest_NO_CONFIGURE)
+run_cmake_test_presets(ConditionRunTests "default" "" "enabled;disabled")
+set(CMakePresetsTest_NO_CONFIGURE 1)
unset(CMakePresetsTest_FILE)
run_cmake_test_presets(NoConfigurePreset "" "" "noConfigurePreset")
@@ -98,6 +104,7 @@ 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")
set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
set(CMakePresetsTest_NO_CONFIGURE 0)
diff --git a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake
index 3416205bc..e95cd1516 100644
--- a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake
+++ b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake
@@ -13,4 +13,11 @@ function(get_test_prerequirements found_var config_file)
"\nset(RPMBUILD_EXECUTABLE \"${RPMBUILD_EXECUTABLE}\")")
set(${found_var} true PARENT_SCOPE)
endif()
+
+ # optional tool for some tests
+ find_program(OBJDUMP_EXECUTABLE objdump)
+ if(OBJDUMP_EXECUTABLE)
+ file(APPEND "${config_file}"
+ "\nset(OBJDUMP_EXECUTABLE \"${OBJDUMP_EXECUTABLE}\")")
+ endif()
endfunction()
diff --git a/Tests/RunCMake/CPack/RPM/default_expected_stderr.txt b/Tests/RunCMake/CPack/RPM/default_expected_stderr.txt
index 6c87ca0c0..404076bda 100644
--- a/Tests/RunCMake/CPack/RPM/default_expected_stderr.txt
+++ b/Tests/RunCMake/CPack/RPM/default_expected_stderr.txt
@@ -1 +1,2 @@
-^(CPackRPM: Will use GENERATED spec file: (/[^/]*)*/Tests/RunCMake/RPM\.[^/]*/CPack/[^-]*(-package-target)?-build((-[^-]*-subtest/)|/)_CPack_Packages/.*/RPM/SPECS/[^\.]*\.spec(\n|$))*$
+^(CPackRPM: Will use GENERATED spec file: (/[^/]*)*/Tests/RunCMake/RPM\.[^/]*/CPack/[^-]*(-package-target)?-build((-[^-]*-subtest/)|/)_CPack_Packages/.*/RPM/SPECS/[^\.]*\.spec(
+|$))*$
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index 15bfb60ee..746ff8b1c 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -16,7 +16,7 @@ run_cpack_test(VERSION "RPM.VERSION;DEB.VERSION" false "MONOLITHIC;COMPONENT")
run_cpack_test(EXTRA "DEB.EXTRA" false "COMPONENT")
run_cpack_test_subtests(GENERATE_SHLIBS "soversion_not_zero;soversion_zero" "DEB.GENERATE_SHLIBS" true "COMPONENT")
run_cpack_test(GENERATE_SHLIBS_LDCONFIG "DEB.GENERATE_SHLIBS_LDCONFIG" true "COMPONENT")
-run_cpack_test(INSTALL_SCRIPTS "RPM.INSTALL_SCRIPTS" false "COMPONENT")
+run_cpack_test_subtests(INSTALL_SCRIPTS "default;single_debug_info;no_scripts;no_scripts_single_debug_info" "RPM.INSTALL_SCRIPTS" false "COMPONENT")
run_cpack_test(LONG_FILENAMES "DEB.LONG_FILENAMES" false "MONOLITHIC")
run_cpack_test_subtests(MAIN_COMPONENT "invalid;found" "RPM.MAIN_COMPONENT" false "COMPONENT")
run_cpack_test(MINIMAL "RPM.MINIMAL;DEB.MINIMAL;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;External" false "MONOLITHIC;COMPONENT")
@@ -37,6 +37,7 @@ unset(ENVIRONMENT)
run_cpack_test(USER_FILELIST "RPM.USER_FILELIST" false "MONOLITHIC")
run_cpack_test(MD5SUMS "DEB.MD5SUMS" false "MONOLITHIC;COMPONENT")
run_cpack_test_subtests(CPACK_INSTALL_SCRIPTS "singular;plural;both" "ZIP" false "MONOLITHIC")
+run_cpack_test(CPACK_CUSTOM_INSTALL_VARIABLES "ZIP" false "MONOLITHIC")
run_cpack_test(DEB_PACKAGE_VERSION_BACK_COMPATIBILITY "DEB.DEB_PACKAGE_VERSION_BACK_COMPATIBILITY" false "MONOLITHIC;COMPONENT")
run_cpack_test_subtests(EXTERNAL "none;good;good_multi;bad_major;bad_minor;invalid_good;invalid_bad;stage_and_package" "External" false "MONOLITHIC;COMPONENT")
run_cpack_test_subtests(
diff --git a/Tests/RunCMake/CPack/VerifyResult.cmake b/Tests/RunCMake/CPack/VerifyResult.cmake
index 0ab545a28..76c1bea7c 100644
--- a/Tests/RunCMake/CPack/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/VerifyResult.cmake
@@ -29,8 +29,16 @@ file(READ "${bin_dir}/test_output.txt" output)
file(READ "${bin_dir}/test_error.txt" error)
file(READ "${config_file}" config_file_content)
-set(output_error_message
- "\nCPack output: '${output}'\nCPack error: '${error}';\nCPack result: '${PACKAGING_RESULT}';\nconfig file: '${config_file_content}'")
+string(REPLACE "\n" "\n cpack-out> " cpack_out "\n${output}")
+string(REPLACE "\n" "\n cpack-err> " cpack_err "\n${error}")
+string(REPLACE "\n" "\n cpack-res> " cpack_res "\n${PACKAGING_RESULT}")
+string(REPLACE "\n" "\n cpack-cfg> " cpack_cfg "\n${config_file_content}")
+string(CONCAT output_error_message
+ "CPack output:${cpack_out}\n"
+ "CPack error:${cpack_err}\n"
+ "CPack result:${cpack_res}\n"
+ "CPack config file:${cpack_cfg}"
+ )
# generate default expected files data
include("${src_dir}/tests/${RunCMake_TEST_FILE_PREFIX}/ExpectedFiles.cmake")
@@ -74,22 +82,22 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0)
string(REPLACE "\n" "\n actual> " msg_actual "\n${PACKAGE_CONTENT}")
string(REPLACE "\n" "\n expect> " msg_expected "\n${EXPECTED_FILE_CONTENT_${file_no_}}")
message(FATAL_ERROR
- "Unexpected file content for file No. '${file_no_}'!\n"
+ "Unexpected file content for file ${file_no_}!\n"
"The content was:${msg_actual}\n"
"which does not match:${msg_expected}\n"
"${output_error_message}")
endif()
- elseif(foundFilescount_ EQUAL 0)
+ elseif(foundFilesCount_ EQUAL 0)
message(FATAL_ERROR
- "Found no files for file No. '${file_no_}'!"
- " Globbing expression: '${EXPECTED_FILE_${file_no_}}'"
+ "Found no files for file ${file_no_}!\n"
+ "Globbing expression:\n '${EXPECTED_FILE_${file_no_}}'\n"
"${output_error_message}")
else()
message(FATAL_ERROR
- "Found more than one file for file No. '${file_no_}'!"
- " Found files count '${foundFilesCount_}'."
- " Files: '${FOUND_FILE_${file_no_}}'"
- " Globbing expression: '${EXPECTED_FILE_${file_no_}}'"
+ "Found more than one file for file ${file_no_}!\n"
+ "Found files count '${foundFilesCount_}'.\n"
+ "Files:\n '${FOUND_FILE_${file_no_}}'\n"
+ "Globbing expression:\n '${EXPECTED_FILE_${file_no_}}'\n"
"${output_error_message}")
endif()
endforeach()
@@ -105,7 +113,8 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0)
if(NOT foundFilesCount_ EQUAL allFoundFilesCount_)
message(FATAL_ERROR
- "Found more files than expected! Found files: '${allFoundFiles_}'"
+ "Found more files than expected!\n"
+ "Found files:\n '${allFoundFiles_}'\n"
"${output_error_message}")
endif()
@@ -116,8 +125,9 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0)
if(found_ EQUAL -1)
message(FATAL_ERROR
- "Expected files don't match found files! Found files:"
- " '${allFoundFiles_}'"
+ "Expected files don't match found files!\n"
+ "Found files:\n"
+ " '${allFoundFiles_}'\n"
"${output_error_message}")
endif()
endforeach()
@@ -127,7 +137,7 @@ else()
file(GLOB checkMissingFiles_ RELATIVE "${bin_dir}" "${missing_file_glob_}")
if(checkMissingFiles_)
- message(FATAL_ERROR "Unexpected files found: '${checkMissingFiles_}'"
+ message(FATAL_ERROR "Unexpected files found:\n '${checkMissingFiles_}'\n"
"${output_error_message}")
endif()
endforeach()
diff --git a/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/ExpectedFiles.cmake
new file mode 100644
index 000000000..a05513b2f
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/ExpectedFiles.cmake
@@ -0,0 +1,7 @@
+set(EXPECTED_FILES_COUNT "1")
+set(EXPECTED_FILE_CONTENT_1_LIST
+ "/foo"
+ "/foo/bar.txt"
+ "/foo/baz.txt"
+ "/foo/foo.txt"
+)
diff --git a/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/test.cmake b/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/test.cmake
new file mode 100644
index 000000000..4a12f1987
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/test.cmake
@@ -0,0 +1,7 @@
+set(CPACK_CUSTOM_INSTALL_VARIABLES "FOO=foo.txt" "BAR=bar.txt")
+
+install(CODE [[
+ file(WRITE ${CMAKE_INSTALL_PREFIX}/foo/${FOO})
+ file(WRITE ${CMAKE_INSTALL_PREFIX}/foo/${BAR})
+ file(WRITE ${CMAKE_INSTALL_PREFIX}/foo/baz.txt)
+]])
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/RPM-COMPONENT-stderr.txt b/Tests/RunCMake/CPack/tests/DEBUGINFO/RPM-COMPONENT-stderr.txt
new file mode 100644
index 000000000..8f798bbfd
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/RPM-COMPONENT-stderr.txt
@@ -0,0 +1,17 @@
+^CMake Warning \(dev\) at [^
+]*/Modules/Internal/CPack/CPackRPM.cmake:[0-9]+ \(message\):
+ CPackRPM:Warning: debuginfo package was requested but will not be generated
+ as no source files were found! Component: 'appheaders'.
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/Internal/CPack/CPackRPM.cmake:[0-9]+ \(cpack_rpm_generate_package\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CPackRPM: Will use GENERATED spec file: [^
+]*/Tests/RunCMake/RPM.DEBUGINFO/CPack/DEBUGINFO-build/_CPack_Packages/Linux/RPM/SPECS/Debuginfo-appheaders.spec
+CPackRPM: Will use GENERATED spec file: [^
+]*/Tests/RunCMake/RPM.DEBUGINFO/CPack/DEBUGINFO-build/_CPack_Packages/Linux/RPM/SPECS/Debuginfo-applications.spec
+CPackRPM: Will use GENERATED spec file: [^
+]*/Tests/RunCMake/RPM.DEBUGINFO/CPack/DEBUGINFO-build/_CPack_Packages/Linux/RPM/SPECS/Debuginfo-headers.spec
+CPackRPM: Will use GENERATED spec file: [^
+]*/Tests/RunCMake/RPM.DEBUGINFO/CPack/DEBUGINFO-build/_CPack_Packages/Linux/RPM/SPECS/Debuginfo-libs.spec$
diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake
index de38df9ef..5a87c442b 100644
--- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake
@@ -1,5 +1,10 @@
+if(RunCMake_SUBTEST_SUFFIX MATCHES ".*single_debug_info")
+ set(EXPECTED_FILE_1 "install_scripts-0.1.1-1.*.rpm")
+else()
+ set(EXPECTED_FILE_1_COMPONENT "foo")
+endif()
+
set(EXPECTED_FILES_COUNT "2")
-set(EXPECTED_FILE_1_COMPONENT "foo")
set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
set(EXPECTED_FILE_2_COMPONENT "bar")
set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-no_scripts_single_debug_info-stderr.txt b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-no_scripts_single_debug_info-stderr.txt
new file mode 100644
index 000000000..8d98f9deb
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-no_scripts_single_debug_info-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt
new file mode 100644
index 000000000..8d98f9deb
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake
new file mode 100644
index 000000000..90cfe4467
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake
@@ -0,0 +1,11 @@
+function(get_test_prerequirements found_var config_file)
+ if(SUBTEST_SUFFIX MATCHES ".*single_debug_info")
+ include(${config_file})
+
+ if(OBJDUMP_EXECUTABLE)
+ set(${found_var} true PARENT_SCOPE)
+ endif()
+ else()
+ set(${found_var} true PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/VerifyResult.cmake
index 1a1e98373..0c42d9069 100644
--- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/VerifyResult.cmake
@@ -7,23 +7,34 @@ function(checkScripts_ FILE COMPARE_LIST)
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
- string(REPLACE "\n" ";" FILE_SCRIPTS_LIST_ "${FILE_SCRIPTS_}")
+ if(COMPARE_LIST STREQUAL "")
+ if(NOT FILE_SCRIPTS_ STREQUAL "")
+ message(FATAL_ERROR "No scripts were expected in '${FILE}'; file info: '${FILE_SCRIPTS_}'")
+ endif()
+ else()
+ string(REPLACE "\n" ";" FILE_SCRIPTS_LIST_ "${FILE_SCRIPTS_}")
+
+ foreach(COMPARE_REGEX_ IN LISTS COMPARE_LIST)
+ unset(FOUND_)
- foreach(COMPARE_REGEX_ IN LISTS COMPARE_LIST)
- unset(FOUND_)
+ foreach(COMPARE_ IN LISTS FILE_SCRIPTS_LIST_)
+ if(COMPARE_ MATCHES "${COMPARE_REGEX_}")
+ set(FOUND_ true)
+ break()
+ endif()
+ endforeach()
- foreach(COMPARE_ IN LISTS FILE_SCRIPTS_LIST_)
- if(COMPARE_ MATCHES "${COMPARE_REGEX_}")
- set(FOUND_ true)
- break()
+ if(NOT FOUND_)
+ message(FATAL_ERROR "Missing scripts in '${FILE}'; file info: '${FILE_SCRIPTS_}'; missing: '${COMPARE_REGEX_}'")
endif()
endforeach()
-
- if(NOT FOUND_)
- message(FATAL_ERROR "Missing scripts in '${FILE}'; file info: '${FILE_SCRIPTS_}'; missing: '${COMPARE_REGEX_}'")
- endif()
- endforeach()
+ endif()
endfunction()
-checkScripts_("${FOUND_FILE_1}" "echo \"pre install foo\";echo \"post install foo\";echo \"pre uninstall foo\";echo \"post uninstall foo\";echo \"pre trans foo\";echo \"post trans foo\"")
-checkScripts_("${FOUND_FILE_2}" "echo \"pre install\";echo \"post install\";echo \"pre uninstall\";echo \"post uninstall\";echo \"pre trans\";echo \"post trans\"")
+if(RunCMake_SUBTEST_SUFFIX MATCHES "no_scripts.*")
+ checkScripts_("${FOUND_FILE_1}" "")
+ checkScripts_("${FOUND_FILE_2}" "")
+else()
+ checkScripts_("${FOUND_FILE_1}" "echo \"pre install foo\";echo \"post install foo\";echo \"pre uninstall foo\";echo \"post uninstall foo\";echo \"pre trans foo\";echo \"post trans foo\"")
+ checkScripts_("${FOUND_FILE_2}" "echo \"pre install\";echo \"post install\";echo \"pre uninstall\";echo \"post uninstall\";echo \"pre trans\";echo \"post trans\"")
+endif()
diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake
index c200fa502..ce5db0cfe 100644
--- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake
+++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake
@@ -1,60 +1,70 @@
if(GENERATOR_TYPE STREQUAL "RPM")
- set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh")
- set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/post_install.sh")
- set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall.sh")
- set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall.sh")
- set(CPACK_RPM_PRE_TRANS_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/pre_trans.sh")
- set(CPACK_RPM_POST_TRANS_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/post_trans.sh")
-
- set(CPACK_RPM_foo_PRE_INSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/pre_install_foo.sh")
- set(CPACK_RPM_foo_POST_INSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/post_install_foo.sh")
- set(CPACK_RPM_foo_PRE_UNINSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall_foo.sh")
- set(CPACK_RPM_foo_POST_UNINSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall_foo.sh")
- set(CPACK_RPM_foo_PRE_TRANS_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh")
- set(CPACK_RPM_foo_POST_TRANS_SCRIPT_FILE
- "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh")
+ if(RunCMake_SUBTEST_SUFFIX MATCHES ".*single_debug_info")
+ set(CPACK_RPM_MAIN_COMPONENT "foo")
+ set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON)
+ set(CPACK_RPM_FOO_FILE_NAME "RPM-DEFAULT")
+ endif()
endif()
set(CMAKE_BUILD_WITH_INSTALL_RPATH 1)
-# default
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh"
- "echo \"pre install\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_install.sh"
- "echo \"post install\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall.sh"
- "echo \"pre uninstall\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall.sh"
- "echo \"post uninstall\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_trans.sh"
- "echo \"pre trans\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_trans.sh"
- "echo \"post trans\"\n")
+if(NOT RunCMake_SUBTEST_SUFFIX MATCHES "no_scripts.*")
+ if(GENERATOR_TYPE STREQUAL "RPM")
+ set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh")
+ set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/post_install.sh")
+ set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall.sh")
+ set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall.sh")
+ set(CPACK_RPM_PRE_TRANS_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/pre_trans.sh")
+ set(CPACK_RPM_POST_TRANS_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/post_trans.sh")
+
+ set(CPACK_RPM_foo_PRE_INSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/pre_install_foo.sh")
+ set(CPACK_RPM_foo_POST_INSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/post_install_foo.sh")
+ set(CPACK_RPM_foo_PRE_UNINSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall_foo.sh")
+ set(CPACK_RPM_foo_POST_UNINSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall_foo.sh")
+ set(CPACK_RPM_foo_PRE_TRANS_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh")
+ set(CPACK_RPM_foo_POST_TRANS_SCRIPT_FILE
+ "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh")
+ endif()
-# specific
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_install_foo.sh"
- "echo \"pre install foo\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_install_foo.sh"
- "echo \"post install foo\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall_foo.sh"
- "echo \"pre uninstall foo\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall_foo.sh"
- "echo \"post uninstall foo\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh"
- "echo \"pre trans foo\"\n")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh"
- "echo \"post trans foo\"\n")
+ # default
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh"
+ "echo \"pre install\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_install.sh"
+ "echo \"post install\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall.sh"
+ "echo \"pre uninstall\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall.sh"
+ "echo \"post uninstall\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_trans.sh"
+ "echo \"pre trans\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_trans.sh"
+ "echo \"post trans\"\n")
+
+ # specific
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_install_foo.sh"
+ "echo \"pre install foo\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_install_foo.sh"
+ "echo \"post install foo\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall_foo.sh"
+ "echo \"pre uninstall foo\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall_foo.sh"
+ "echo \"post uninstall foo\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh"
+ "echo \"pre trans foo\"\n")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh"
+ "echo \"post trans foo\"\n")
+endif()
install(FILES CMakeLists.txt DESTINATION foo COMPONENT foo)
install(FILES CMakeLists.txt DESTINATION bar COMPONENT bar)
diff --git a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake
index 936e4ed80..1dc70848a 100644
--- a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake
@@ -9,7 +9,7 @@ if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL
set(EXPECTED_FILE_2 "single_debuginfo*-headers.rpm")
set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
set(EXPECTED_FILE_3 "single_debuginfo*-libs.rpm")
- set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so")
+ set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so;/empty_dir")
set(EXPECTED_FILE_4_COMPONENT "debuginfo")
set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*")
diff --git a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake
index 60e9038fe..064539ecd 100644
--- a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake
+++ b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake
@@ -30,6 +30,9 @@ if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid"
OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo")
install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers)
install(TARGETS test_lib DESTINATION bas COMPONENT libs)
+
+ # test that we correctly handle empty dir in non main component
+ install(DIRECTORY DESTINATION empty_dir COMPONENT libs)
elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component"
OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo")
set(CPACK_COMPONENTS_ALL applications)
diff --git a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake
index 73d7481f1..42e8384a8 100644
--- a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake
@@ -18,14 +18,20 @@ execute_process(COMMAND ${RPMBUILD_EXECUTABLE} --define "_topdir ${CMAKE_CURRENT
OUTPUT_QUIET
)
-set(output_error_message_
- "\n${RPMBUILD_EXECUTABLE} error: '${error_}';\nresult: '${result_}';\n${output_error_message}")
+string(REPLACE "\n" "\n rpmbuild-err> " rpmbuild_err "\n${error_}")
+string(REPLACE "\n" "\n rpmbuild-res> " rpmbuild_res "\n${result_}")
+string(CONCAT output_error_message_
+ "${RPMBUILD_EXECUTABLE} error:${rpmbuild_err}\n"
+ "${RPMBUILD_EXECUTABLE} result:${rpmbuild_res}\n"
+ "${output_error_message}"
+ )
# expected file content are test_prog and optional build-id links that are
# generated by rpmbuild (introduced in rpm 4.13.0.1)
set(EXPECTED_FILE_CONTENT_ "^/foo${whitespaces_}/foo/test_prog(${whitespaces_}.*\.build-id.*)*$")
+set(EXPECTED_FILE_ "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS/*.rpm")
-file(GLOB_RECURSE FOUND_FILE_ RELATIVE "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS" "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS/*.rpm")
+file(GLOB_RECURSE FOUND_FILE_ RELATIVE "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS" "${EXPECTED_FILE_}")
list(APPEND foundFiles_ "${FOUND_FILE_}")
list(LENGTH FOUND_FILE_ foundFilesCount_)
@@ -37,17 +43,27 @@ if(foundFilesCount_ EQUAL 1)
expected_content_list "${PACKAGE_CONTENT}")
if(NOT expected_content_list)
+ string(REPLACE "\n" "\n actual> " msg_actual "\n${PACKAGE_CONTENT}")
+ string(REPLACE "\n" "\n expect> " msg_expected "\n${EXPECTED_FILE_CONTENT_}")
+ string(REPLACE "\r" "\\r" msg_expected "${msg_expected}")
+ string(REPLACE "\t" "\\t" msg_expected "${msg_expected}")
message(FATAL_ERROR
"Unexpected file content!\n"
- " Content: '${PACKAGE_CONTENT}'\n\n"
- " Expected: '${EXPECTED_FILE_CONTENT_}'"
+ "The content was:${msg_actual}\n"
+ "which does not match:${msg_expected}\n"
"${output_error_message_}")
endif()
+elseif(foundFilesCount_ EQUAL 0)
+ message(FATAL_ERROR
+ "Found no files!\n"
+ "Globbing expression:\n '${EXPECTED_FILE_}'\n"
+ "${output_error_message_}")
else()
message(FATAL_ERROR
- "Found more than one file!"
- " Found files count '${foundFilesCount_}'."
- " Files: '${FOUND_FILE_}'"
+ "Found more than one file!\n"
+ "Found files count '${foundFilesCount_}'.\n"
+ "Files:\n '${FOUND_FILE_}'\n"
+ "Globbing expression:\n '${EXPECTED_FILE_}'\n"
"${output_error_message_}")
endif()
@@ -62,6 +78,7 @@ list(LENGTH allFoundFiles_ allFoundFilesCount_)
if(NOT foundFilesCount_ EQUAL allFoundFilesCount_)
message(FATAL_ERROR
- "Found more files than expected! Found files: '${allFoundFiles_}'"
- "${output_error_message_}")
+ "Found more files than expected!\n"
+ "Found files:\n '${allFoundFiles_}'\n"
+ "${output_error_message_}")
endif()
diff --git a/Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake
index 61ce752fe..d1d615be7 100644
--- a/Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake
@@ -1,15 +1,13 @@
-execute_process(COMMAND ${RPMBUILD_EXECUTABLE} --querytags
- OUTPUT_VARIABLE RPMBUILD_CAPS
- RESULT_VARIABLE RPMBUILD_CAPS_RESULT)
+# CPack uses `rpm --suggests` to check if rpmbuild supports the "Suggests:" tag.
+# This test intentionally uses a different method (build a test .spec) so any
+# problems will be caught early if functionality should change in the future.
+execute_process(
+ COMMAND ${RPMBUILD_EXECUTABLE} --nobuild test_suggests.spec
+ ERROR_QUIET
+ RESULT_VARIABLE RPMBUILD_SUGGESTS_RESULT)
-if(NOT RPMBUILD_CAPS_RESULT)
- string(REPLACE "\n" ";" RPMBUILD_CAPS "${RPMBUILD_CAPS}")
- cmake_policy(PUSH)
- cmake_policy(SET CMP0057 NEW)
- if(SUGGESTS IN_LIST RPMBUILD_CAPS)
- set(should_contain_suggests_tag_ true)
- endif()
- cmake_policy(POP)
+if(RPMBUILD_SUGGESTS_RESULT EQUAL 0)
+ set(should_contain_suggests_tag_ true)
endif()
# Only verify that suggests tag is present only if that tag is supported.
diff --git a/Tests/RunCMake/CPack/tests/SUGGESTS/test_suggests.spec b/Tests/RunCMake/CPack/tests/SUGGESTS/test_suggests.spec
new file mode 100644
index 000000000..e766fa95c
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/SUGGESTS/test_suggests.spec
@@ -0,0 +1,22 @@
+# This spec file is used to check if the provided version of rpmbuild supports the "Suggests:" tag
+
+Name: test
+Version: 0
+Release: 1
+Summary: test
+License: test
+
+Suggests: suggested_package
+
+%description
+
+
+%prep
+
+%build
+%configure
+%install
+%clean
+%files
+%doc
+%changelog
diff --git a/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake b/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake
index 6f3720131..af39e5f2c 100644
--- a/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake
+++ b/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake
@@ -1,6 +1,6 @@
install(FILES CMakeLists.txt DESTINATION foo COMPONENT test)
-set(CPACK_THREADS 0)
+set(CPACK_THREADS "-4")
if(PACKAGING_TYPE STREQUAL "COMPONENT")
set(CPACK_COMPONENTS_ALL test)
diff --git a/Tests/RunCMake/CPackSymlinks/RunCMakeTest.cmake b/Tests/RunCMake/CPackSymlinks/RunCMakeTest.cmake
index 439d95e61..5a8b7a08c 100644
--- a/Tests/RunCMake/CPackSymlinks/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPackSymlinks/RunCMakeTest.cmake
@@ -15,6 +15,7 @@ function(run_cpack_symlink_test)
run_cmake_command(SrcSymlinksCPack
${CMAKE_CPACK_COMMAND} --config CPackSourceConfig.cmake
)
+ run_cmake_script(SrcSymlinksCheck)
endfunction()
run_cpack_symlink_test()
diff --git a/Tests/RunCMake/CPackSymlinks/SrcSymlinksCheck.cmake b/Tests/RunCMake/CPackSymlinks/SrcSymlinksCheck.cmake
new file mode 100644
index 000000000..0041c9249
--- /dev/null
+++ b/Tests/RunCMake/CPackSymlinks/SrcSymlinksCheck.cmake
@@ -0,0 +1,21 @@
+set(dir ${CMAKE_CURRENT_SOURCE_DIR})
+
+set(tarball ${dir}/SrcSymlinks-0.1-Source.tar.gz)
+set(extrdir ${dir}/SrcSymlinks-0.1-Source)
+
+message(STATUS "Extracting ${tarball} in ${dir}...")
+execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ${tarball}
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE output
+ ERROR_VARIABLE output
+ WORKING_DIRECTORY ${dir})
+message(STATUS "result='${result}'")
+message(STATUS "output='${output}'")
+
+if(NOT ${result} EQUAL 0)
+ message(FATAL_ERROR "Cannot unpack source tarball")
+endif()
+
+if(NOT EXISTS ${extrdir}/dirlink/src.h)
+ message(FATAL_ERROR "${extrdir}/dirlink/src.h not found")
+endif()
diff --git a/Tests/RunCMake/CPackSymlinks/SrcSymlinksTar-stdout.txt b/Tests/RunCMake/CPackSymlinks/SrcSymlinksTar-stdout.txt
index 24ad12472..8b1ae5746 100644
--- a/Tests/RunCMake/CPackSymlinks/SrcSymlinksTar-stdout.txt
+++ b/Tests/RunCMake/CPackSymlinks/SrcSymlinksTar-stdout.txt
@@ -1,7 +1,6 @@
-^x CMakeLists.txt
-x cygwin/
-x cygwin/build.sh
-x cygwin/setup.patch
+^x build.sh
+x CMakeLists.txt
+x dirlink
x include/
x include/src.h
x link.h
diff --git a/Tests/RunCMake/CPackSymlinks/testcpacksym.tar b/Tests/RunCMake/CPackSymlinks/testcpacksym.tar
index a44c656e8..c24af48a2 100644
--- a/Tests/RunCMake/CPackSymlinks/testcpacksym.tar
+++ b/Tests/RunCMake/CPackSymlinks/testcpacksym.tar
Binary files differ
diff --git a/Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-stderr.txt b/Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-stderr.txt
new file mode 100644
index 000000000..e6f93256b
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-stderr.txt
@@ -0,0 +1,3 @@
+Cannot find file: [^
+]*/Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-build/DartConfiguration.tcl
+Binary directory is not set. No coverage checking will be performed.$
diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
index 6cf1476ca..4b654f852 100644
--- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
@@ -202,7 +202,7 @@ function(run_TestLoad name load)
add_test(TestLoad1 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\")
add_test(TestLoad2 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\")
")
- run_cmake_command(${name} ${CMAKE_CTEST_COMMAND} -j2 --test-load ${load})
+ run_cmake_command(${name} ${CMAKE_CTEST_COMMAND} -VV -j2 --test-load ${load})
endfunction()
# Tests for the --test-load feature of ctest
@@ -360,6 +360,10 @@ run_NoTests()
# Check the configuration type variable is passed
run_ctest(check-configuration-type)
+run_cmake_command(EmptyDirCoverage-ctest
+ ${CMAKE_CTEST_COMMAND} -C Debug -M Experimental -T Coverage
+ )
+
function(run_MemCheckSan case opts)
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/MemCheckSan${case}-build)
@@ -397,3 +401,22 @@ function(run_testDir)
run_cmake_command(testDir ${CMAKE_CTEST_COMMAND} --test-dir "${RunCMake_TEST_BINARY_DIR}/sub")
endfunction()
run_testDir()
+
+# Test --output-junit
+function(run_output_junit)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/output-junit)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+add_test(test1 \"${CMAKE_COMMAND}\" -E false)
+add_test(test2 \"${CMAKE_COMMAND}\" -E echo \"hello world\")
+add_test(test3 \"${CMAKE_COMMAND}\" -E true)
+set_tests_properties(test3 PROPERTIES DISABLED \"ON\")
+add_test(test4 \"${CMAKE_COMMAND}/doesnt_exist\")
+add_test(test5 \"${CMAKE_COMMAND}\" -E echo \"please skip\")
+set_tests_properties(test5 PROPERTIES SKIP_REGULAR_EXPRESSION \"please skip\")
+")
+ run_cmake_command(output-junit ${CMAKE_CTEST_COMMAND} --output-junit "${RunCMake_TEST_BINARY_DIR}/junit.xml")
+endfunction()
+run_output_junit()
diff --git a/Tests/RunCMake/CTestCommandLine/output-junit-check.cmake b/Tests/RunCMake/CTestCommandLine/output-junit-check.cmake
new file mode 100644
index 000000000..b270fdf6a
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/output-junit-check.cmake
@@ -0,0 +1,36 @@
+file(GLOB junit_xml_file "${RunCMake_TEST_BINARY_DIR}/junit.xml")
+if(junit_xml_file)
+ file(READ "${junit_xml_file}" junit_xml LIMIT 4096)
+ if(NOT "${junit_xml}" MATCHES "tests=\"5\"")
+ set(RunCMake_TEST_FAILED "tests=\"5\" not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "failures=\"1\"")
+ set(RunCMake_TEST_FAILED "failures=\"1\" not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "disabled=\"1\"")
+ set(RunCMake_TEST_FAILED "disabled=\"1\" not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "skipped=\"2\"")
+ set(RunCMake_TEST_FAILED "skipped=\"2\" not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "<system-out>hello world")
+ set(RunCMake_TEST_FAILED "<system-out>hello world not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "<system-out>Disabled")
+ set(RunCMake_TEST_FAILED "<system-out>Disabled not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "<skipped message=\"Unable to find executable\"/>")
+ set(RunCMake_TEST_FAILED "<skipped message=\"Unable to find executable\"/> not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "<system-out>Unable to find executable:")
+ set(RunCMake_TEST_FAILED "<system-out>Unable to find executable: not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "<skipped message=\"SKIP_REGULAR_EXPRESSION_MATCHED\"/>")
+ set(RunCMake_TEST_FAILED "<skipped message=\"SKIP_REGULAR_EXPRESSION_MATCHED\"/> not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "<system-out>please skip")
+ set(RunCMake_TEST_FAILED "<system-out>please skip not found when expected")
+ endif()
+else()
+ set(RunCMake_TEST_FAILED "junit.xml not found")
+endif()
diff --git a/Tests/RunCMake/CTestCommandLine/output-junit-result.txt b/Tests/RunCMake/CTestCommandLine/output-junit-result.txt
new file mode 100644
index 000000000..45a4fb75d
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/output-junit-result.txt
@@ -0,0 +1 @@
+8
diff --git a/Tests/RunCMake/CTestCommandLine/output-junit-stderr.txt b/Tests/RunCMake/CTestCommandLine/output-junit-stderr.txt
new file mode 100644
index 000000000..ce30dc80d
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/output-junit-stderr.txt
@@ -0,0 +1 @@
+Unable to find executable: .*doesnt_exist
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt
index 7ee3daee1..5101985f1 100644
--- a/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt
@@ -1,7 +1,20 @@
-^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad
+Test project [^
+]*/Tests/RunCMake/CTestCommandLine/TestLoad(
+[^*][^
+]*)*
+test 1
Start 1: TestLoad1
++(
+[^*][^
+]*)*
+test 2
Start 2: TestLoad2
-1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec
++(
+[^*][^
+]*)*
+1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec(
+[^*][^
+]*)*
2/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 2
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
index 7ee3daee1..5101985f1 100644
--- a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
@@ -1,7 +1,20 @@
-^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad
+Test project [^
+]*/Tests/RunCMake/CTestCommandLine/TestLoad(
+[^*][^
+]*)*
+test 1
Start 1: TestLoad1
++(
+[^*][^
+]*)*
+test 2
Start 2: TestLoad2
-1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec
++(
+[^*][^
+]*)*
+1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec(
+[^*][^
+]*)*
2/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 2
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt
index 11a768a9c..db7d7f34b 100644
--- a/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt
@@ -1,8 +1,21 @@
-^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad
+Test project [^
+]*/Tests/RunCMake/CTestCommandLine/TestLoad(
+[^*][^
+]*)*
\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 3, Smallest test TestLoad[1-2] requires 1\*\*\*\*\*
+test 1
Start 1: TestLoad1
++(
+[^*][^
+]*)*
+test 2
Start 2: TestLoad2
-1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec
++(
+[^*][^
+]*)*
+1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec(
+[^*][^
+]*)*
2/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 2
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake
new file mode 100644
index 000000000..339ce1865
--- /dev/null
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake
@@ -0,0 +1,13 @@
+
+enable_language (HIP)
+include(CheckCompilerFlag)
+
+check_compiler_flag(HIP "-_this_is_not_a_flag_" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "invalid HIP compile flag didn't fail.")
+endif()
+
+check_compiler_flag(HIP "-DFOO" SHOULD_WORK)
+if(NOT SHOULD_WORK)
+ message(SEND_ERROR "${CMAKE_HIP_COMPILER_ID} compiler flag '-DFOO' check failed")
+endif()
diff --git a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake
index 7a4e2cebb..7ef1860c6 100644
--- a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake
@@ -22,3 +22,7 @@ endif()
if(CMake_TEST_ISPC)
run_cmake(CheckISPCCompilerFlag)
endif()
+
+if(CMake_TEST_HIP)
+ run_cmake(CheckHIPCompilerFlag)
+endif()
diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake
new file mode 100644
index 000000000..3bf3b3051
--- /dev/null
+++ b/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake
@@ -0,0 +1,3 @@
+
+set (CHECK_LANGUAGE HIP)
+include ("${CMAKE_CURRENT_SOURCE_DIR}/CheckLinkerFlag.cmake")
diff --git a/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake b/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake
index 6ec914806..5e5bff6c9 100644
--- a/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake
@@ -16,3 +16,7 @@ endif()
if (CMake_TEST_CUDA)
run_cmake(CheckCUDALinkerFlag)
endif()
+
+if (CMake_TEST_HIP)
+ run_cmake(CheckHIPLinkerFlag)
+endif()
diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake
new file mode 100644
index 000000000..911a0d7b9
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake
@@ -0,0 +1,27 @@
+
+enable_language (HIP)
+include(CheckSourceCompiles)
+
+check_source_compiles(HIP "I don't build" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "invalid HIP source didn't fail.")
+endif()
+
+check_source_compiles(HIP [=[
+ #include <vector>
+ __device__ int d_func() { }
+ int main() {
+ return 0;
+ }
+]=]
+ SHOULD_BUILD)
+if(NOT SHOULD_BUILD)
+ message(SEND_ERROR "Test fail for valid HIP source.")
+endif()
+
+check_source_compiles(HIP "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 HIP complex source.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake
index 6e9088f82..530f133da 100644
--- a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake
@@ -23,3 +23,7 @@ endif()
if(CMake_TEST_ISPC)
run_cmake(CheckISPCSourceCompiles)
endif()
+
+if(CMake_TEST_HIP)
+ run_cmake(CheckHIPSourceCompiles)
+endif()
diff --git a/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake
new file mode 100644
index 000000000..d9fb8c22a
--- /dev/null
+++ b/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake
@@ -0,0 +1,21 @@
+
+enable_language (HIP)
+include(CheckSourceRuns)
+
+check_source_runs(HIP "int main() {return 2;}" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "HIP check_source_runs succeeded, but should have failed.")
+endif()
+
+check_source_runs(HIP
+[=[
+ #include <vector>
+ __device__ __host__ void fake_function();
+ __host__ int main() {
+ return 0;
+ }
+]=]
+ SHOULD_RUN)
+if(NOT SHOULD_RUN)
+ message(SEND_ERROR "HIP check_source_runs failed for valid HIP executable.")
+endif()
diff --git a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake
index c99ac8be2..478410337 100644
--- a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake
@@ -19,3 +19,7 @@ endif()
if (CMake_TEST_CUDA)
run_cmake(CheckCUDASourceRuns)
endif()
+
+if (CMake_TEST_HIP)
+ run_cmake(CheckHIPSourceRuns)
+endif()
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt
index 16f8be8b0..96de4d17d 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt
@@ -1,3 +1,3 @@
^'--parallel' invalid number '12ab' given\.
+
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-large-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-large-stderr.txt
index e7b9aaaf2..0bb806ff4 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-large-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-large-stderr.txt
@@ -1,3 +1,3 @@
^The <jobs> value is too large\.
+
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-space-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-space-bad-number-stderr.txt
index 16f8be8b0..96de4d17d 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-space-bad-number-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-space-bad-number-stderr.txt
@@ -1,3 +1,3 @@
^'--parallel' invalid number '12ab' given\.
+
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-zero-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-zero-stderr.txt
index d1241f46d..b965d4a47 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-zero-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-zero-stderr.txt
@@ -1,3 +1,3 @@
^The <jobs> value requires a positive integer argument\.
+
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt
index d52b16583..97e90ec99 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt
@@ -1,3 +1,3 @@
^'-j' invalid number '12ab' given\.
+
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-large-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-large-stderr.txt
index e7b9aaaf2..0bb806ff4 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-large-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-large-stderr.txt
@@ -1,3 +1,3 @@
^The <jobs> value is too large\.
+
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-space-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-space-bad-number-stderr.txt
index d52b16583..97e90ec99 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-space-bad-number-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-space-bad-number-stderr.txt
@@ -1,3 +1,3 @@
^'-j' invalid number '12ab' given\.
+
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-zero-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-zero-stderr.txt
index d1241f46d..b965d4a47 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-zero-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-zero-stderr.txt
@@ -1,3 +1,3 @@
^The <jobs> value requires a positive integer argument\.
+
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt
index 2dd9bc424..c15fdbabd 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt
@@ -1,2 +1,2 @@
^Error: Building 'clean' and other targets together is not supported\.
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt
index 2dd9bc424..c15fdbabd 100644
--- a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt
+++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt
@@ -1,2 +1,2 @@
^Error: Building 'clean' and other targets together is not supported\.
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
index c76c92d9e..3df3e523d 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":2}]},{"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":3}]},{"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":{.*}}$
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt
index 21e60eec0..63a10d835 100644
--- a/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt
+++ b/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt
@@ -1 +1 @@
-^CMake Error: failed to create link .* no such file or directory
+^CMake Error: failed to create link '[^']+': [A-Za-z]
diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake b/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake
index 5b97aecc0..d92554af4 100644
--- a/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake
+++ b/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake
@@ -1,3 +1,3 @@
-if(${actual_stderr_var} MATCHES "operation not permitted")
+if(${actual_stderr_var} MATCHES "A required privilege is not held by the client")
unset(msg)
endif()
diff --git a/Tests/RunCMake/CommandLine/E_create_symlink-broken-create-check.cmake b/Tests/RunCMake/CommandLine/E_create_symlink-broken-create-check.cmake
index 5df5f2fb7..43573bfe9 100644
--- a/Tests/RunCMake/CommandLine/E_create_symlink-broken-create-check.cmake
+++ b/Tests/RunCMake/CommandLine/E_create_symlink-broken-create-check.cmake
@@ -1,4 +1,4 @@
-if(${actual_stderr_var} MATCHES "operation not permitted")
+if(${actual_stderr_var} MATCHES "A required privilege is not held by the client")
unset(msg)
else()
if(NOT IS_SYMLINK ${RunCMake_TEST_BINARY_DIR}/L)
diff --git a/Tests/RunCMake/CommandLine/E_create_symlink-broken-replace-check.cmake b/Tests/RunCMake/CommandLine/E_create_symlink-broken-replace-check.cmake
index d37df0169..639c2237e 100644
--- a/Tests/RunCMake/CommandLine/E_create_symlink-broken-replace-check.cmake
+++ b/Tests/RunCMake/CommandLine/E_create_symlink-broken-replace-check.cmake
@@ -1,4 +1,4 @@
-if(${actual_stderr_var} MATCHES "operation not permitted")
+if(${actual_stderr_var} MATCHES "A required privilege is not held by the client")
unset(msg)
else()
if(NOT IS_DIRECTORY ${RunCMake_TEST_BINARY_DIR}/L)
diff --git a/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake b/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake
new file mode 100644
index 000000000..d9fbd5838
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake
@@ -0,0 +1 @@
+set(ENV_TOOLCHAIN 1)
diff --git a/Tests/RunCMake/CommandLine/EnvToolchain.cmake b/Tests/RunCMake/CommandLine/EnvToolchain.cmake
new file mode 100644
index 000000000..230051d0a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchain.cmake
@@ -0,0 +1,3 @@
+message(STATUS "ENV{CMAKE_TOOLCHAIN_FILE}='$ENV{CMAKE_TOOLCHAIN_FILE}'")
+message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'")
+message(STATUS "ENV_TOOLCHAIN='${ENV_TOOLCHAIN}'")
diff --git a/Tests/RunCMake/CommandLine/EnvToolchainAbsolute-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainAbsolute-stdout.txt
new file mode 100644
index 000000000..ab4bbde9b
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchainAbsolute-stdout.txt
@@ -0,0 +1,5 @@
+-- ENV{CMAKE_TOOLCHAIN_FILE}='[^
+]*/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake'
+-- CMAKE_TOOLCHAIN_FILE='[^
+]*/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake'
+-- ENV_TOOLCHAIN='1'
diff --git a/Tests/RunCMake/CommandLine/EnvToolchainAbsolute.cmake b/Tests/RunCMake/CommandLine/EnvToolchainAbsolute.cmake
new file mode 100644
index 000000000..0f91b5eb4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchainAbsolute.cmake
@@ -0,0 +1 @@
+include(EnvToolchain.cmake)
diff --git a/Tests/RunCMake/CommandLine/EnvToolchainIgnore-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainIgnore-stdout.txt
new file mode 100644
index 000000000..4de9505c2
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchainIgnore-stdout.txt
@@ -0,0 +1,4 @@
+-- ENV{CMAKE_TOOLCHAIN_FILE}='[^
+]*/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake'
+-- CMAKE_TOOLCHAIN_FILE=''
+-- ENV_TOOLCHAIN=''
diff --git a/Tests/RunCMake/CommandLine/EnvToolchainIgnore.cmake b/Tests/RunCMake/CommandLine/EnvToolchainIgnore.cmake
new file mode 100644
index 000000000..0f91b5eb4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchainIgnore.cmake
@@ -0,0 +1 @@
+include(EnvToolchain.cmake)
diff --git a/Tests/RunCMake/CommandLine/EnvToolchainNone-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainNone-stdout.txt
new file mode 100644
index 000000000..cfe655d76
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchainNone-stdout.txt
@@ -0,0 +1,3 @@
+-- ENV{CMAKE_TOOLCHAIN_FILE}=''
+-- CMAKE_TOOLCHAIN_FILE=''
+-- ENV_TOOLCHAIN=''
diff --git a/Tests/RunCMake/CommandLine/EnvToolchainNone.cmake b/Tests/RunCMake/CommandLine/EnvToolchainNone.cmake
new file mode 100644
index 000000000..0f91b5eb4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchainNone.cmake
@@ -0,0 +1 @@
+include(EnvToolchain.cmake)
diff --git a/Tests/RunCMake/CommandLine/EnvToolchainNoneExisting-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainNoneExisting-stdout.txt
new file mode 100644
index 000000000..4de9505c2
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchainNoneExisting-stdout.txt
@@ -0,0 +1,4 @@
+-- ENV{CMAKE_TOOLCHAIN_FILE}='[^
+]*/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake'
+-- CMAKE_TOOLCHAIN_FILE=''
+-- ENV_TOOLCHAIN=''
diff --git a/Tests/RunCMake/CommandLine/EnvToolchainRelative-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainRelative-stdout.txt
new file mode 100644
index 000000000..4bafbba7e
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchainRelative-stdout.txt
@@ -0,0 +1,4 @@
+-- ENV{CMAKE_TOOLCHAIN_FILE}='EnvToolchain-toolchain.cmake'
+-- CMAKE_TOOLCHAIN_FILE='[^
+]*/Tests/RunCMake/CommandLine/EnvToolchainRelative-build/EnvToolchain-toolchain.cmake'
+-- ENV_TOOLCHAIN='1'
diff --git a/Tests/RunCMake/CommandLine/EnvToolchainRelative.cmake b/Tests/RunCMake/CommandLine/EnvToolchainRelative.cmake
new file mode 100644
index 000000000..0f91b5eb4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvToolchainRelative.cmake
@@ -0,0 +1 @@
+include(EnvToolchain.cmake)
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index caf3c8896..c58b1d06d 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -69,6 +69,8 @@ run_cmake_command(build-bad-dir
run_cmake_command(build-bad-generator
${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-generator)
+run_cmake_command(install-prefix-no-arg ${CMAKE_COMMAND} -B DummyBuildDir --install-prefix)
+
run_cmake_command(install-no-dir
${CMAKE_COMMAND} --install)
run_cmake_command(install-bad-dir
@@ -162,6 +164,29 @@ project(ExplicitDirsMissing LANGUAGES NONE)
endfunction()
run_ExplicitDirs()
+function(run_Toolchain)
+ set(RunCMake_TEST_NO_SOURCE_DIR 1)
+ set(source_dir ${RunCMake_SOURCE_DIR}/Toolchain)
+
+ run_cmake_with_options(toolchain-no-arg -S ${source_dir} --toolchain=)
+ run_cmake_with_options(toolchain-valid-abs-path -S ${source_dir} --toolchain "${source_dir}/toolchain.cmake")
+ run_cmake_with_options(toolchain-valid-rel-src-path -S ${source_dir} --toolchain=toolchain.cmake)
+
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(binary_dir ${RunCMake_BINARY_DIR}/Toolchain-build)
+ set(RunCMake_TEST_BINARY_DIR "${binary_dir}")
+ file(REMOVE_RECURSE "${binary_dir}")
+
+ # Test that we both search the binary dir for toolchain files, and it takes
+ # precedence over source dir
+ file(WRITE ${binary_dir}/toolchain.cmake [=[
+set(CMAKE_SYSTEM_NAME Linux)
+set(toolchain_file binary_dir)
+]=])
+ run_cmake_with_options(toolchain-valid-rel-build-path ${CMAKE_COMMAND} -S ${source_dir} -B ${binary_dir} --toolchain toolchain.cmake)
+endfunction()
+run_Toolchain()
+
function(run_BuildDir)
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/BuildDir-build)
@@ -288,7 +313,7 @@ function(run_EnvironmentGenerator)
unset(ENV{CMAKE_GENERATOR_PLATFORM})
endif()
# Instance is available since VS 2017.
- if(RunCMake_GENERATOR MATCHES "Visual Studio (15|16).*")
+ if(RunCMake_GENERATOR MATCHES "Visual Studio 1[567].*")
set(ENV{CMAKE_GENERATOR_INSTANCE} "invalid")
# Envvar shouldn't affect existing build tree
run_cmake_command(Envgen-instance-existing ${CMAKE_COMMAND} -E chdir ..
@@ -319,6 +344,33 @@ if(RunCMake_GENERATOR MATCHES "Unix Makefiles" OR RunCMake_GENERATOR MATCHES "Ni
run_EnvironmentExportCompileCommands()
endif()
+function(run_EnvironmentToolchain)
+ set(ENV{CMAKE_TOOLCHAIN_FILE} "${RunCMake_SOURCE_DIR}/EnvToolchain-toolchain.cmake")
+ run_cmake(EnvToolchainAbsolute)
+ run_cmake_with_options(EnvToolchainIgnore -DCMAKE_TOOLCHAIN_FILE=)
+ unset(ENV{CMAKE_TOOLCHAIN_FILE})
+
+ set(ENV{CMAKE_TOOLCHAIN_FILE} "EnvToolchain-toolchain.cmake")
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EnvToolchainRelative-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ configure_file("${RunCMake_SOURCE_DIR}/EnvToolchain-toolchain.cmake" "${RunCMake_TEST_BINARY_DIR}/EnvToolchain-toolchain.cmake" COPYONLY)
+ run_cmake(EnvToolchainRelative)
+ unset(ENV{CMAKE_TOOLCHAIN_FILE})
+ unset(RunCMake_TEST_NO_CLEAN)
+
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EnvToolchainNone-build)
+ run_cmake(EnvToolchainNone)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}/CMakeFiles")
+ set(ENV{CMAKE_TOOLCHAIN_FILE} "${RunCMake_SOURCE_DIR}/EnvToolchain-toolchain.cmake")
+ run_cmake_command(EnvToolchainNoneExisting ${CMAKE_COMMAND} .)
+ unset(ENV{CMAKE_TOOLCHAIN_FILE})
+ unset(RunCMake_TEST_NO_CLEAN)
+endfunction()
+run_EnvironmentToolchain()
+
if(RunCMake_GENERATOR STREQUAL "Ninja")
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Build-build)
@@ -346,7 +398,7 @@ run_cmake_command(E_create_symlink-missing-dir
# These tests are special on Windows since it will only fail if the user
# running the test does not have the priveldge to create symlinks. If this
# happens we clear the msg in the -check.cmake and say that the test passes
-set(RunCMake_DEFAULT_stderr "(operation not permitted)?")
+set(RunCMake_DEFAULT_stderr "(A required privilege is not held by the client)?")
set(RunCMake_TEST_BINARY_DIR
${RunCMake_BINARY_DIR}/E_create_symlink-broken-build)
set(RunCMake_TEST_NO_CLEAN 1)
@@ -390,7 +442,7 @@ run_cmake_command(E_create_hardlink-no-directory
#On Windows, if the user does not have sufficient privileges
#don't fail this test
-set(RunCMake_DEFAULT_stderr "(operation not permitted)?")
+set(RunCMake_DEFAULT_stderr "(A required privilege is not held by the client)?")
run_cmake_command(E_create_hardlink-unresolved-symlink-prereq
${CMAKE_COMMAND} -E create_symlink ${dir}/1 ${dir}/1-symlink
)
@@ -549,7 +601,7 @@ file(MAKE_DIRECTORY ${out})
run_cmake_command(E_cat_non_existing_file
${CMAKE_COMMAND} -E cat ${out}/non-existing-file.txt)
-if(UNIX)
+if(UNIX AND NOT MSYS)
# test non readable file only if not root
execute_process(
COMMAND id -u $ENV{USER}
@@ -788,7 +840,7 @@ function(reject_fifo)
run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT})
endif()
endfunction()
-if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN")
+if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN" AND NOT CMAKE_SYSTEM_NAME STREQUAL "MSYS")
reject_fifo()
run_cmake_command(closed_stdin sh -c "\"${CMAKE_COMMAND}\" --version <&-")
run_cmake_command(closed_stdout sh -c "\"${CMAKE_COMMAND}\" --version >&-")
diff --git a/Tests/RunCMake/CommandLine/Toolchain/CMakeLists.txt b/Tests/RunCMake/CommandLine/Toolchain/CMakeLists.txt
new file mode 100644
index 000000000..80d42b828
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Toolchain/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.20)
+project(Toolchain LANGUAGES NONE)
+message(FATAL_ERROR "${toolchain_file}")
diff --git a/Tests/RunCMake/CommandLine/Toolchain/toolchain.cmake b/Tests/RunCMake/CommandLine/Toolchain/toolchain.cmake
new file mode 100644
index 000000000..719556c0a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/Toolchain/toolchain.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_SYSTEM_NAME Linux)
+set(toolchain_file source_dir)
diff --git a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt
index 5fe25390a..fa3adc874 100644
--- a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt
+++ b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt
@@ -1,2 +1 @@
-^CMake Error: '--target=invalid' is invalid syntax for --target
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+^Error: could not load cache
diff --git a/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt b/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt
index 9b4d26bc2..4811bea2f 100644
--- a/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt
+++ b/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt
@@ -1 +1 @@
-^Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+^Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt
index c8f1a03cb..559e4b613 100644
--- a/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt
+++ b/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt
@@ -1,2 +1,2 @@
^Unknown argument --invalid-command
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt
index d69338a41..1f44c4e33 100644
--- a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt
+++ b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt
@@ -1,2 +1,2 @@
-^CMake Error: '--targetinvalid' is invalid syntax for --target
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+^Unknown argument --targetinvalid
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt
index a6cfeceac..4f5ba558b 100644
--- a/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt
+++ b/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt
@@ -1,2 +1,2 @@
^Unknown argument -invalid-command
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-result.txt b/Tests/RunCMake/CommandLine/install-prefix-no-arg-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-result.txt
+++ b/Tests/RunCMake/CommandLine/install-prefix-no-arg-result.txt
diff --git a/Tests/RunCMake/CommandLine/install-prefix-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/install-prefix-no-arg-stderr.txt
new file mode 100644
index 000000000..a464c7000
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/install-prefix-no-arg-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: No install directory specified for --install-prefix
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-result.txt b/Tests/RunCMake/CommandLine/toolchain-no-arg-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-result.txt
+++ b/Tests/RunCMake/CommandLine/toolchain-no-arg-result.txt
diff --git a/Tests/RunCMake/CommandLine/toolchain-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/toolchain-no-arg-stderr.txt
new file mode 100644
index 000000000..2fec517a5
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/toolchain-no-arg-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: No file specified for --toolchain
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-result.txt b/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-result.txt
+++ b/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-result.txt
diff --git a/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-stderr.txt b/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-stderr.txt
new file mode 100644
index 000000000..21d5db646
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-stderr.txt
@@ -0,0 +1 @@
+^CMake Error.*source_dir
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-result.txt b/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-result.txt
+++ b/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-result.txt
diff --git a/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-stderr.txt b/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-stderr.txt
new file mode 100644
index 000000000..198005166
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-stderr.txt
@@ -0,0 +1 @@
+^CMake Error.*binary_dir
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-result.txt b/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-result.txt
+++ b/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-result.txt
diff --git a/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-stderr.txt b/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-stderr.txt
new file mode 100644
index 000000000..21d5db646
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-stderr.txt
@@ -0,0 +1 @@
+^CMake Error.*source_dir
diff --git a/Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/C-launch-env-Build-stdout.txt
index 3313e31f6..3313e31f6 100644
--- a/Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt
+++ b/Tests/RunCMake/CompilerLauncher/C-launch-env-Build-stdout.txt
diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CUDA-launch-env-Build-stdout.txt
index 3313e31f6..3313e31f6 100644
--- a/Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt
+++ b/Tests/RunCMake/CompilerLauncher/CUDA-launch-env-Build-stdout.txt
diff --git a/Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CXX-launch-env-Build-stdout.txt
index 3313e31f6..3313e31f6 100644
--- a/Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt
+++ b/Tests/RunCMake/CompilerLauncher/CXX-launch-env-Build-stdout.txt
diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/Fortran-launch-env-Build-stdout.txt
index 3313e31f6..3313e31f6 100644
--- a/Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt
+++ b/Tests/RunCMake/CompilerLauncher/Fortran-launch-env-Build-stdout.txt
diff --git a/Tests/RunCMake/CompilerLauncher/HIP-common.cmake b/Tests/RunCMake/CompilerLauncher/HIP-common.cmake
new file mode 100644
index 000000000..53ece7814
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/HIP-common.cmake
@@ -0,0 +1,5 @@
+enable_language(HIP)
+enable_language(CXX)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+
+add_executable(main main.hip)
diff --git a/Tests/RunCMake/CompilerLauncher/ISPC-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/HIP-env-Build-stdout.txt
index 3313e31f6..3313e31f6 100644
--- a/Tests/RunCMake/CompilerLauncher/ISPC-env-launch-Build-stdout.txt
+++ b/Tests/RunCMake/CompilerLauncher/HIP-env-Build-stdout.txt
diff --git a/Tests/RunCMake/CompilerLauncher/HIP-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/HIP-env-launch-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/HIP-env-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/HIP-env.cmake b/Tests/RunCMake/CompilerLauncher/HIP-env.cmake
new file mode 100644
index 000000000..1bf56cee9
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/HIP-env.cmake
@@ -0,0 +1 @@
+include(HIP-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/HIP-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/HIP-launch-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/HIP-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/HIP-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/HIP-launch-env.cmake
new file mode 100644
index 000000000..37985a52a
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/HIP-launch-env.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(HIP-env.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/HIP-launch.cmake b/Tests/RunCMake/CompilerLauncher/HIP-launch.cmake
new file mode 100644
index 000000000..78fd16ba0
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/HIP-launch.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(HIP.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/HIP.cmake b/Tests/RunCMake/CompilerLauncher/HIP.cmake
new file mode 100644
index 000000000..9d2577a69
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/HIP.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_HIP_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
+include(HIP-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/ISPC-launch-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/ISPC-launch-env-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/ISPC-launch-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
index 293d71199..84d047982 100644
--- a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
@@ -1,7 +1,7 @@
include(RunCMake)
function(run_compiler_launcher lang)
- # Use a single build tree for tests without cleaning.
+ # Preserve build tree so we can reuse it for the ${lang}-Build subtest below
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${lang}-build)
set(RunCMake_TEST_NO_CLEAN 1)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
@@ -29,6 +29,9 @@ endif()
if(CMake_TEST_Fortran)
list(APPEND langs Fortran)
endif()
+if(CMake_TEST_HIP)
+ list(APPEND langs HIP)
+endif()
if(CMake_TEST_ISPC)
list(APPEND langs ISPC)
endif()
diff --git a/Tests/RunCMake/CompilerLauncher/main.hip b/Tests/RunCMake/CompilerLauncher/main.hip
new file mode 100644
index 000000000..f8b643afb
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/main.hip
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake b/Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake
index 2b4fc8931..3876cebe9 100644
--- a/Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake
@@ -13,7 +13,7 @@ function(run_single_config_test label config exclude_from_all_value expectation)
run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config ${config})
endfunction()
-run_single_config_test("explictly not excluded" Debug 0 "should_exist")
+run_single_config_test("explicitly not excluded" Debug 0 "should_exist")
run_single_config_test("excluded" Debug 1 "should_not_exist")
if(RunCMake_GENERATOR MATCHES "^(Xcode|Visual Studio)")
diff --git a/Tests/RunCMake/ExternalProject/MultiCommand.cmake b/Tests/RunCMake/ExternalProject/MultiCommand.cmake
index dbf67eb71..084965806 100644
--- a/Tests/RunCMake/ExternalProject/MultiCommand.cmake
+++ b/Tests/RunCMake/ExternalProject/MultiCommand.cmake
@@ -1,6 +1,6 @@
include(ExternalProject)
-# Verify COMMAND keyword is recognised after various *_COMMAND options
+# Verify COMMAND keyword is recognized after various *_COMMAND options
ExternalProject_Add(multiCommand
DOWNLOAD_COMMAND "${CMAKE_COMMAND}" -E echo "download 1"
COMMAND "${CMAKE_COMMAND}" -E echo "download 2"
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake b/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake
index fb78e8789..91cdf7ca1 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake
@@ -4,6 +4,7 @@ set(expect
query/client-foo/query.json
reply
reply/codemodel-v2-[0-9a-f]+\\.json
+ .*
reply/index-[0-9.T-]+\\.json
.*
)
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake b/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake
index 7c6a35ab5..9aa9e4a2a 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake
@@ -4,6 +4,7 @@ set(expect
query/client-foo/codemodel-v2
reply
reply/codemodel-v2-[0-9a-f]+\\.json
+ .*
reply/index-[0-9.T-]+\\.json
.*
)
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake b/Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake
index cc2f31b94..43d1a0b4e 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake
@@ -3,6 +3,7 @@ set(expect
query/codemodel-v2
reply
reply/codemodel-v2-[0-9a-f]+\\.json
+ .*
reply/index-[0-9.T-]+\\.json
.*
)
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
index df2410a41..6cf57a3a9 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
@@ -12,7 +12,7 @@ def read_codemodel_json_data(filename):
def check_objects(o, g):
assert is_list(o)
assert len(o) == 1
- check_index_object(o[0], "codemodel", 2, 2, check_object_codemodel(g))
+ check_index_object(o[0], "codemodel", 2, 3, check_object_codemodel(g))
def check_backtrace(t, b, backtrace):
btg = t["backtraceGraph"]
@@ -55,7 +55,7 @@ def check_backtraces(t, actual, expected):
def check_directory(c):
def _check(actual, expected):
assert is_dict(actual)
- expected_keys = ["build", "source", "projectIndex"]
+ expected_keys = ["build", "jsonFile", "source", "projectIndex"]
assert matches(actual["build"], expected["build"])
assert is_int(actual["projectIndex"])
@@ -92,10 +92,111 @@ def check_directory(c):
assert sorted(actual.keys()) == sorted(expected_keys)
+ assert is_string(actual["jsonFile"])
+ filepath = os.path.join(reply_dir, actual["jsonFile"])
+ with open(filepath) as f:
+ d = json.load(f)
+
+ assert is_dict(d)
+ assert sorted(d.keys()) == ["backtraceGraph", "installers", "paths"]
+
+ assert is_string(d["paths"]["source"], actual["source"])
+ assert is_string(d["paths"]["build"], actual["build"])
+
+ check_backtrace_graph(d["backtraceGraph"])
+
+ assert is_list(d["installers"])
+ assert len(d["installers"]) == len(expected["installers"])
+ for a, e in zip(d["installers"], expected["installers"]):
+ assert is_dict(a)
+ expected_keys = ["component", "type"]
+
+ assert is_string(a["component"], e["component"])
+ assert is_string(a["type"], e["type"])
+
+ if e["destination"] is not None:
+ expected_keys.append("destination")
+ assert is_string(a["destination"], e["destination"])
+
+ if e["paths"] is not None:
+ expected_keys.append("paths")
+ assert is_list(a["paths"])
+ assert len(a["paths"]) == len(e["paths"])
+
+ for ap, ep in zip(a["paths"], e["paths"]):
+ if is_string(ep):
+ assert matches(ap, ep)
+ else:
+ assert is_dict(ap)
+ assert sorted(ap.keys()) == ["from", "to"]
+ assert matches(ap["from"], ep["from"])
+ assert matches(ap["to"], ep["to"])
+
+ if e["isExcludeFromAll"] is not None:
+ expected_keys.append("isExcludeFromAll")
+ assert is_bool(a["isExcludeFromAll"], e["isExcludeFromAll"])
+
+ if e["isForAllComponents"] is not None:
+ expected_keys.append("isForAllComponents")
+ assert is_bool(a["isForAllComponents"], e["isForAllComponents"])
+
+ if e["isOptional"] is not None:
+ expected_keys.append("isOptional")
+ assert is_bool(a["isOptional"], e["isOptional"])
+
+ if e["targetId"] is not None:
+ expected_keys.append("targetId")
+ assert matches(a["targetId"], e["targetId"])
+
+ if e["targetIndex"] is not None:
+ expected_keys.append("targetIndex")
+ assert is_int(a["targetIndex"])
+ assert c["targets"][a["targetIndex"]]["name"] == e["targetIndex"]
+
+ if e["targetIsImportLibrary"] is not None:
+ expected_keys.append("targetIsImportLibrary")
+ assert is_bool(a["targetIsImportLibrary"], e["targetIsImportLibrary"])
+
+ if e["targetInstallNamelink"] is not None:
+ expected_keys.append("targetInstallNamelink")
+ assert is_string(a["targetInstallNamelink"], e["targetInstallNamelink"])
+
+ if e["exportName"] is not None:
+ expected_keys.append("exportName")
+ assert is_string(a["exportName"], e["exportName"])
+
+ if e["exportTargets"] is not None:
+ expected_keys.append("exportTargets")
+ assert is_list(a["exportTargets"])
+ assert len(a["exportTargets"]) == len(e["exportTargets"])
+ for at, et in zip(a["exportTargets"], e["exportTargets"]):
+ 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["scriptFile"] is not None:
+ expected_keys.append("scriptFile")
+ assert is_string(a["scriptFile"], e["scriptFile"])
+
+ if e.get("runtimeDependencySetName", None) is not None:
+ expected_keys.append("runtimeDependencySetName")
+ assert is_string(a["runtimeDependencySetName"], e["runtimeDependencySetName"])
+
+ if e.get("runtimeDependencySetType", None) is not None:
+ expected_keys.append("runtimeDependencySetType")
+ assert is_string(a["runtimeDependencySetType"], e["runtimeDependencySetType"])
+
+ if e["backtrace"] is not None:
+ expected_keys.append("backtrace")
+ check_backtrace(d, a["backtrace"], e["backtrace"])
+
+ assert sorted(a.keys()) == sorted(expected_keys)
+
return _check
-def check_target_backtrace_graph(t):
- btg = t["backtraceGraph"]
+def check_backtrace_graph(btg):
assert is_dict(btg)
assert sorted(btg.keys()) == ["commands", "files", "nodes"]
assert is_list(btg["commands"])
@@ -148,7 +249,7 @@ def check_target(c):
assert is_string(obj["name"], expected["name"])
assert matches(obj["id"], expected["id"])
assert is_string(obj["type"], expected["type"])
- check_target_backtrace_graph(obj)
+ check_backtrace_graph(obj["backtraceGraph"])
assert is_dict(obj["paths"])
assert sorted(obj["paths"].keys()) == ["build", "source"]
@@ -543,6 +644,28 @@ def gen_check_directories(c, g):
for e in expected:
e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(ALL_BUILD|ZERO_CHECK)"), e["targetIds"])
+ if sys.platform in ("win32", "cygwin", "msys") or "aix" in sys.platform:
+ for e in expected:
+ e["installers"] = list(filter(lambda i: i["targetInstallNamelink"] is None or i["targetInstallNamelink"] == "skip", e["installers"]))
+ for i in e["installers"]:
+ i["targetInstallNamelink"] = None
+
+ if sys.platform not in ("win32", "cygwin", "msys"):
+ for e in expected:
+ e["installers"] = list(filter(lambda i: not i.get("_dllExtra", False), e["installers"]))
+ if "aix" not in sys.platform:
+ for i in e["installers"]:
+ if "pathsNamelink" in i:
+ i["paths"] = i["pathsNamelink"]
+
+ if sys.platform not in ("win32", "darwin") and "linux" not in sys.platform:
+ for e in expected:
+ e["installers"] = list(filter(lambda i: i["type"] != "runtimeDependencySet", e["installers"]))
+
+ if sys.platform != "darwin":
+ for e in expected:
+ e["installers"] = list(filter(lambda i: i.get("runtimeDependencySetType", None) != "framework", e["installers"]))
+
return expected
def check_directories(c, g):
@@ -705,6 +828,13 @@ def gen_check_targets(c, g, inSource):
if sys.platform not in ("win32", "cygwin", "msys"):
for e in expected:
e["artifacts"] = filter_list(lambda a: not a["_dllExtra"], e["artifacts"])
+ if e["install"] is not None:
+ e["install"]["destinations"] = filter_list(lambda d: "_dllExtra" not in d or not d["_dllExtra"], e["install"]["destinations"])
+
+ else:
+ for e in expected:
+ if e["install"] is not None:
+ e["install"]["destinations"] = filter_list(lambda d: "_namelink" not in d or not d["_namelink"], e["install"]["destinations"])
if "aix" not in sys.platform:
for e in expected:
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json
index 9f0c48a01..6514910a8 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json
@@ -11,5 +11,6 @@
],
"projectName": "Alias",
"minimumCMakeVersion": "3.12",
- "hasInstallRule": null
+ "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 afd41f328..c89e4f9dd 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json
@@ -11,5 +11,6 @@
],
"projectName": "Custom",
"minimumCMakeVersion": "3.12",
- "hasInstallRule": null
+ "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 a51b6eb8d..8052c1a55 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json
@@ -17,5 +17,165 @@
],
"projectName": "Cxx",
"minimumCMakeVersion": "3.12",
- "hasInstallRule": null
+ "hasInstallRule": true,
+ "installers": [
+ {
+ "component": "Unspecified",
+ "type": "target",
+ "destination": "lib",
+ "paths": [
+ "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_exe(\\.exe)?$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": "^cxx_exe::@a56b12a3f5c0529fb296$",
+ "targetIndex": "cxx_exe",
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": 38,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "runtimeDependencySet",
+ "destination": "lib",
+ "paths": null,
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "runtimeDependencySetType": "library",
+ "backtrace": [
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": 38,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "runtimeDependencySet",
+ "destination": "fw",
+ "paths": null,
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "runtimeDependencySetType": "framework",
+ "backtrace": [
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": 38,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "runtimeDependencySet",
+ "destination": "lib",
+ "paths": null,
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "runtimeDependencySetType": "library",
+ "runtimeDependencySetName": "deps",
+ "backtrace": [
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": 43,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "runtimeDependencySet",
+ "destination": "fw",
+ "paths": null,
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "runtimeDependencySetType": "framework",
+ "runtimeDependencySetName": "deps",
+ "backtrace": [
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": 43,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ]
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json
index afbd43a3e..8509f084c 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json
@@ -8,5 +8,6 @@
"targetIds": null,
"projectName": "codemodel-v2",
"minimumCMakeVersion": "3.12",
- "hasInstallRule": null
+ "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 3737ad5fe..27184cd5e 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json
@@ -6,5 +6,6 @@
"targetIds": null,
"projectName": "codemodel-v2",
"minimumCMakeVersion": "3.12",
- "hasInstallRule": null
+ "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 521e3c70d..6d2952d14 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json
@@ -10,5 +10,71 @@
],
"projectName": "External",
"minimumCMakeVersion": "3.12",
- "hasInstallRule": null
+ "hasInstallRule": true,
+ "installers": [
+ {
+ "component": "Unspecified",
+ "type": "directory",
+ "destination": "dir3",
+ "paths": [
+ "^.*/Tests/RunCMake/FileAPIExternalSource/\\.$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+ "line": 15,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "directory",
+ "destination": "dir4",
+ "paths": [
+ "^.*/Tests/RunCMake/FileAPIExternalSource$"
+ ],
+ "isExcludeFromAll": true,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+ "line": 16,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ]
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json
index a41b79b51..92b952640 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json
@@ -14,5 +14,67 @@
],
"projectName": "Imported",
"minimumCMakeVersion": "3.12",
- "hasInstallRule": null
+ "hasInstallRule": true,
+ "installers": [
+ {
+ "component": "Unspecified",
+ "type": "importedRuntimeArtifacts",
+ "destination": "lib",
+ "paths": null,
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^imported/CMakeLists\\.txt$",
+ "line": 32,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^imported/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "importedRuntimeArtifacts",
+ "destination": "lib2",
+ "paths": null,
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": true,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^imported/CMakeLists\\.txt$",
+ "line": 35,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^imported/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ]
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json
index b10d49605..90664dc72 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json
@@ -10,5 +10,6 @@
],
"projectName": "Interface",
"minimumCMakeVersion": "3.12",
- "hasInstallRule": null
+ "hasInstallRule": null,
+ "installers": []
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json
index 1e647ad1b..44bc72545 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json
@@ -13,5 +13,71 @@
],
"projectName": "Object",
"minimumCMakeVersion": "3.13",
- "hasInstallRule": true
+ "hasInstallRule": true,
+ "installers": [
+ {
+ "component": "Unspecified",
+ "type": "target",
+ "destination": "bin",
+ "paths": [
+ "^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?c_object_exe(\\.exe)?$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": "^c_object_exe::@5ed5358f70faf8d8af7a$",
+ "targetIndex": "c_object_exe",
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^object/CMakeLists\\.txt$",
+ "line": 13,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^object/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "target",
+ "destination": "bin",
+ "paths": [
+ "^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_object_exe(\\.exe)?$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": "^cxx_object_exe::@5ed5358f70faf8d8af7a$",
+ "targetIndex": "cxx_object_exe",
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^object/CMakeLists\\.txt$",
+ "line": 13,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^object/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ]
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
index 736d1f5a3..99287fb6f 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
@@ -25,5 +25,603 @@
],
"projectName": "codemodel-v2",
"minimumCMakeVersion": "3.12",
- "hasInstallRule": true
+ "hasInstallRule": true,
+ "installers": [
+ {
+ "component": "Tools",
+ "type": "target",
+ "destination": "bin",
+ "paths": [
+ "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_exe(\\.exe)?$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": "^cxx_exe::@a56b12a3f5c0529fb296$",
+ "targetIndex": "cxx_exe",
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 38,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "target",
+ "destination": "lib",
+ "paths": [
+ "^((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(lib|dll\\.a)$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$",
+ "targetIndex": "c_shared_lib",
+ "targetIsImportLibrary": true,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "_dllExtra": true,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 41,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "target",
+ "destination": "lib",
+ "paths": [
+ "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg|msys-)?c_shared_lib(-1)?\\.(dll|so)$"
+ ],
+ "pathsNamelink": [
+ "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(so\\.1\\.2\\.3|1\\.2\\.3\\.dylib)$",
+ "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(so\\.1|1\\.dylib)$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$",
+ "targetIndex": "c_shared_lib",
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": "skip",
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 41,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "target",
+ "destination": "lib",
+ "paths": [
+ "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?cxx_shared_lib\\.(lib|dll\\.a)$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
+ "targetIndex": "cxx_shared_lib",
+ "targetIsImportLibrary": true,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "_dllExtra": true,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 41,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "target",
+ "destination": "lib",
+ "paths": [
+ "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg|msys-)?cxx_shared_lib\\.(dll|so|dylib)$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
+ "targetIndex": "cxx_shared_lib",
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 41,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "target",
+ "destination": "lib",
+ "paths": [
+ "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(dll|so|dylib)$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$",
+ "targetIndex": "c_shared_lib",
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": "only",
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 46,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "file",
+ "destination": "include",
+ "paths": [
+ {
+ "from": "^empty\\.h$",
+ "to": "^empty-renamed\\.h$"
+ }
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": true,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 48,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "file",
+ "destination": "include",
+ "paths": [
+ "^codemodel-v2\\.cmake$",
+ "^empty\\.h$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 49,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "directory",
+ "destination": "dir1",
+ "paths": [
+ "^\\.$",
+ "^dir$",
+ {
+ "from": "^cxx$",
+ "to": "^\\.$"
+ }
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": true,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 50,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "directory",
+ "destination": "dir2",
+ "paths": [
+ {
+ "from": "^\\.$",
+ "to": "^FileAPI$"
+ },
+ "^dir$",
+ {
+ "from": "^cxx$",
+ "to": "^\\.$"
+ }
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 51,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "export",
+ "destination": "lib/cmake/foo",
+ "paths": [
+ "^CMakeFiles/Export/lib/cmake/foo/FooTargets\\.cmake$"
+ ],
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": "FooTargets",
+ "exportTargets": [
+ {
+ "id": "^cxx_exe::@a56b12a3f5c0529fb296$",
+ "index": "cxx_exe"
+ }
+ ],
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 52,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "script",
+ "destination": null,
+ "paths": null,
+ "isExcludeFromAll": null,
+ "isForAllComponents": null,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": "InstallScript.cmake",
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 53,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "component": "Unspecified",
+ "type": "code",
+ "destination": null,
+ "paths": null,
+ "isExcludeFromAll": null,
+ "isForAllComponents": true,
+ "isOptional": null,
+ "targetId": null,
+ "targetIndex": null,
+ "targetIsImportLibrary": null,
+ "targetInstallNamelink": null,
+ "exportName": null,
+ "exportTargets": null,
+ "scriptFile": null,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 54,
+ "command": "install",
+ "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
+ }
+ ]
+ }
+ ]
}
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 176a8575b..e3a8d0b2d 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
@@ -90,10 +90,10 @@
}
],
"folder": null,
- "nameOnDisk": "^(lib|cyg)?c_shared_lib\\.(so|dylib|dll)$",
+ "nameOnDisk": "^(lib|cyg|msys-)?c_shared_lib(-1)?\\.(so|dylib|dll)$",
"artifacts": [
{
- "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib\\.(so|dylib|dll)$",
+ "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?c_shared_lib(-1)?\\.(so|dylib|dll)$",
"_dllExtra": false
},
{
@@ -101,13 +101,106 @@
"_dllExtra": true
},
{
- "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib\\.pdb$",
+ "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?c_shared_lib(-1)?\\.pdb$",
"_dllExtra": true
}
],
"build": "^\\.$",
"source": "^\\.$",
- "install": null,
+ "install": {
+ "prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$",
+ "destinations": [
+ {
+ "path": "lib",
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 41,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "path": "lib",
+ "_dllExtra": true,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 41,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "path": "lib",
+ "_namelink": true,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 46,
+ "command": "install",
+ "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
+ }
+ ]
+ }
+ ]
+ },
"link": {
"language": "C",
"lto": true,
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 c9e652b2a..385fa622d 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json
@@ -115,6 +115,23 @@
"prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$",
"destinations": [
{
+ "path": "lib",
+ "backtrace": [
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": 38,
+ "command": "install",
+ "hasParent": true
+ },
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
"path": "bin",
"backtrace": [
{
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 171a4f5c1..73e8e127b 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
@@ -66,10 +66,10 @@
}
],
"folder": null,
- "nameOnDisk": "^(lib|cyg)?cxx_shared_lib\\.(so|dylib|dll)$",
+ "nameOnDisk": "^(lib|cyg|msys-)?cxx_shared_lib\\.(so|dylib|dll)$",
"artifacts": [
{
- "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?cxx_shared_lib\\.(so|dylib|dll)$",
+ "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?cxx_shared_lib\\.(so|dylib|dll)$",
"_dllExtra": false
},
{
@@ -77,13 +77,106 @@
"_dllExtra": true
},
{
- "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?cxx_shared_lib\\.pdb$",
+ "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?cxx_shared_lib\\.pdb$",
"_dllExtra": true
}
],
"build": "^cxx$",
"source": "^cxx$",
- "install": null,
+ "install": {
+ "prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$",
+ "destinations": [
+ {
+ "path": "lib",
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 41,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "path": "lib",
+ "_dllExtra": true,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 41,
+ "command": "install",
+ "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
+ }
+ ]
+ },
+ {
+ "path": "lib",
+ "_namelink": true,
+ "backtrace": [
+ {
+ "file": "^codemodel-v2\\.cmake$",
+ "line": 46,
+ "command": "install",
+ "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
+ }
+ ]
+ }
+ ]
+ },
"link": {
"language": "CXX",
"lto": null,
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake
index 240595442..da928ebfc 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake
+++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake
@@ -35,4 +35,20 @@ if(_ipo)
file(WRITE "${CMAKE_BINARY_DIR}/ipo_enabled.txt" "")
endif()
-install(TARGETS cxx_exe)
+install(TARGETS cxx_exe COMPONENT Tools EXPORT FooTargets)
+
+set_target_properties(c_shared_lib PROPERTIES VERSION 1.2.3 SOVERSION 1)
+install(TARGETS c_shared_lib cxx_shared_lib
+ ARCHIVE DESTINATION lib
+ RUNTIME DESTINATION lib
+ LIBRARY DESTINATION lib NAMELINK_SKIP
+ )
+install(TARGETS c_shared_lib cxx_shared_lib LIBRARY NAMELINK_ONLY)
+
+install(FILES empty.h TYPE INCLUDE RENAME empty-renamed.h OPTIONAL)
+install(FILES codemodel-v2.cmake empty.h DESTINATION include)
+install(DIRECTORY . dir cxx/ OPTIONAL DESTINATION dir1)
+install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/dir" "${CMAKE_CURRENT_SOURCE_DIR}/cxx/" DESTINATION dir2)
+install(EXPORT FooTargets DESTINATION lib/cmake/foo)
+install(SCRIPT InstallScript.cmake)
+install(CODE "message(foo)" ALL_COMPONENTS)
diff --git a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
index 76235f5c5..3ae3b60a1 100644
--- a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
+++ b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
@@ -16,7 +16,7 @@ target_link_libraries(cxx_static_exe PRIVATE cxx_static_lib)
target_compile_options(cxx_exe PUBLIC TargetCompileOptions)
target_link_options(cxx_exe PUBLIC TargetLinkOptions)
-target_link_directories(cxx_exe PUBLIC "${CMAKE_BINARY_DIR}/TargetLinkDir")
+target_link_directories(cxx_exe PUBLIC "$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/TargetLinkDir>")
target_precompile_headers(cxx_exe PUBLIC ../empty.h)
@@ -30,3 +30,18 @@ if(CMAKE_CXX_STANDARD_DEFAULT AND DEFINED CMAKE_CXX11_STANDARD_COMPILE_OPTION)
target_compile_features(cxx_standard_compile_feature_exe PRIVATE cxx_decltype)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx_std_11.txt" "")
endif()
+
+set(_rdeps)
+if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Windows|Darwin)$")
+ set(_rdeps RUNTIME_DEPENDENCIES)
+endif()
+install(TARGETS cxx_exe ${_rdeps}
+ DESTINATION lib
+ FRAMEWORK DESTINATION fw
+ )
+if(_rdeps)
+ install(RUNTIME_DEPENDENCY_SET deps
+ DESTINATION lib
+ FRAMEWORK DESTINATION fw
+ )
+endif()
diff --git a/Tests/RunCMake/FileAPI/imported/CMakeLists.txt b/Tests/RunCMake/FileAPI/imported/CMakeLists.txt
index f79d87c82..770838b6a 100644
--- a/Tests/RunCMake/FileAPI/imported/CMakeLists.txt
+++ b/Tests/RunCMake/FileAPI/imported/CMakeLists.txt
@@ -28,3 +28,10 @@ endif()
add_library(imported_interface_lib INTERFACE IMPORTED)
add_executable(link_imported_interface_exe ../empty.c)
target_link_libraries(link_imported_interface_exe PRIVATE imported_interface_lib)
+
+install(IMPORTED_RUNTIME_ARTIFACTS imported_shared_lib
+ DESTINATION lib
+)
+install(IMPORTED_RUNTIME_ARTIFACTS imported_shared_lib
+ DESTINATION lib2 OPTIONAL
+)
diff --git a/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt b/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt
index b3ca66075..2865864a3 100644
--- a/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt
+++ b/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt
@@ -11,3 +11,6 @@ set_property(SOURCE empty.c PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY
target_include_directories(generated_exe SYSTEM PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
target_compile_definitions(generated_exe PRIVATE GENERATED_EXE=1 -DTGT_DUMMY)
set_source_files_properties(empty.c PROPERTIES COMPILE_OPTIONS SRC_COMPILE_OPTIONS_DUMMY)
+
+install(DIRECTORY . DESTINATION dir3)
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} EXCLUDE_FROM_ALL DESTINATION dir4)
diff --git a/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake b/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake
index 0000ef971..a5e66dc3a 100644
--- a/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake
+++ b/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake
@@ -11,5 +11,6 @@ file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/custom
add_custom_target(checkCustomFilePermissions ALL
COMMAND ${CMAKE_COMMAND}
-DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/customfilepermissions.txt
+ -DMSYS=${MSYS}
-P "${CMAKE_CURRENT_SOURCE_DIR}/CustomFilePermissionsVerify.cmake"
)
diff --git a/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake b/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake
index a87e916d5..2ef32815f 100644
--- a/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake
+++ b/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake
@@ -2,7 +2,7 @@ if(NOT EXISTS "${generatedFile}")
message(SEND_ERROR "Missing file:\n ${generatedFile}")
endif()
-if (UNIX)
+if (UNIX AND NOT MSYS)
find_program(STAT_EXECUTABLE NAMES stat)
if(NOT STAT_EXECUTABLE)
return()
diff --git a/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake b/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake
index 7981ccce1..5e5b16afc 100644
--- a/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake
+++ b/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake
@@ -2,7 +2,7 @@ if(NOT EXISTS "${generatedFile}")
message(SEND_ERROR "Missing generated file:\n ${generatedFile}")
endif()
-if (UNIX)
+if (UNIX AND NOT MSYS)
find_program(STAT_EXECUTABLE NAMES stat)
if(NOT STAT_EXECUTABLE)
return()
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt
index 4c2e35fcc..4d7370c47 100644
--- a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt
@@ -3,7 +3,7 @@ CMake Error at OutputNameMatchesObjects.cmake:[0-9]+ \(file\):
\$<TARGET_OBJECTS:foo>
- Objects of target "foo" referenced but is not an allowed library types
- \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\).
+ Objects of target "foo" referenced but is not one of the allowed target
+ types \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\).
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake
new file mode 100644
index 000000000..cb3dd69af
--- /dev/null
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake
@@ -0,0 +1,17 @@
+# Prepare environment to reuse empty.pc
+file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pc-empty/lib/pkgconfig" PC_PATH)
+if(UNIX)
+ string(REPLACE "\\ " " " PC_PATH "${PC_PATH}")
+endif()
+set(ENV{PKG_CONFIG_PATH} "${PC_PATH}")
+
+find_package(PkgConfig REQUIRED)
+pkg_search_module(Empty REQUIRED empty IMPORTED_TARGET)
+
+if(NOT Empty_MODULE_NAME STREQUAL "empty")
+ message(FATAL_ERROR "Wrong value for Empty_MODULE_NAME. Expected: empty, got: ${Empty_MODULE_NAME}")
+endif()
+
+if(NOT TARGET PkgConfig::Empty)
+ message(FATAL_ERROR "PkgConfig::Empty target not created")
+endif()
diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
index 4e6eef6f0..e7f008ca5 100644
--- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
@@ -29,4 +29,5 @@ if (PKG_CONFIG_FOUND)
run_cmake(FindPkgConfig_IMPORTED_TARGET)
run_cmake(FindPkgConfig_VERSION_OPERATORS)
run_cmake(FindPkgConfig_GET_MATCHING_MODULE_NAME)
+ run_cmake(FindPkgConfig_empty_target)
endif ()
diff --git a/Tests/RunCMake/FindPkgConfig/pc-empty/lib/pkgconfig/empty.pc b/Tests/RunCMake/FindPkgConfig/pc-empty/lib/pkgconfig/empty.pc
new file mode 100644
index 000000000..954c5f81c
--- /dev/null
+++ b/Tests/RunCMake/FindPkgConfig/pc-empty/lib/pkgconfig/empty.pc
@@ -0,0 +1,5 @@
+Name: Empty
+Description: Dummy package to test empty target
+Version: 1.0
+Libs:
+Cflags:
diff --git a/Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt b/Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt
new file mode 100644
index 000000000..bd75ccdf4
--- /dev/null
+++ b/Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt
@@ -0,0 +1 @@
+xxx/no/exist/fw\.framework/Versions/A/fwxxx
diff --git a/Tests/RunCMake/Framework/ImportedFrameworkTest.cmake b/Tests/RunCMake/Framework/ImportedFrameworkTest.cmake
new file mode 100644
index 000000000..42edaea4f
--- /dev/null
+++ b/Tests/RunCMake/Framework/ImportedFrameworkTest.cmake
@@ -0,0 +1,10 @@
+add_library(fw SHARED IMPORTED)
+set_target_properties(fw PROPERTIES
+ FRAMEWORK TRUE
+ IMPORTED_LOCATION "/no/exist/fw.framework/Versions/A/fw"
+ IMPORTED_SONAME "@rpath/fw.framework/Versions/A/fw"
+ )
+
+add_custom_target(print_fw ALL COMMAND
+ ${CMAKE_COMMAND} -E echo "xxx$<TARGET_SONAME_FILE:fw>xxx"
+ )
diff --git a/Tests/RunCMake/Framework/RunCMakeTest.cmake b/Tests/RunCMake/Framework/RunCMakeTest.cmake
index 6ee61a30b..36eaf5c94 100644
--- a/Tests/RunCMake/Framework/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Framework/RunCMakeTest.cmake
@@ -81,3 +81,15 @@ function(framework_multi_config_postfix_test)
endfunction()
framework_multi_config_postfix_test()
+
+function(imported_framework_test)
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/ImportedFrameworkTest-build")
+ set(RunCMake_TEST_NO_CLEAN 1)
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(ImportedFrameworkTest)
+ run_cmake_command(ImportedFrameworkTest-build ${CMAKE_COMMAND} --build .)
+endfunction()
+
+imported_framework_test()
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-stderr.txt
deleted file mode 100644
index c8f773a0a..000000000
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-stderr.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-CMake Error at COMPILE_LANGUAGE-add_custom_command.cmake:2 \(add_custom_command\):
- Error evaluating generator expression:
-
- \$<COMPILE_LANGUAGE>
-
- \$<COMPILE_LANGUAGE:...> may only be used to specify include directories,
- compile definitions, compile options, and to evaluate components of the
- file\(GENERATE\) command.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-stderr.txt
deleted file mode 100644
index 7025838b1..000000000
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-stderr.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-CMake Error at COMPILE_LANGUAGE-add_custom_target.cmake:1 \(add_custom_target\):
- Error evaluating generator expression:
-
- \$<COMPILE_LANGUAGE>
-
- \$<COMPILE_LANGUAGE:...> may only be used to specify include directories,
- compile definitions, compile options, and to evaluate components of the
- file\(GENERATE\) command.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake
index 15a5e79eb..3e6e08083 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake
@@ -1,11 +1,11 @@
include(RunCMake)
-run_cmake(COMPILE_LANGUAGE-add_custom_target)
-run_cmake(COMPILE_LANGUAGE-add_custom_command)
-run_cmake(COMPILE_LANGUAGE-install)
-run_cmake(COMPILE_LANGUAGE-target_sources)
-run_cmake(COMPILE_LANGUAGE-add_executable)
-run_cmake(COMPILE_LANGUAGE-add_library)
-run_cmake(COMPILE_LANGUAGE-add_test)
-run_cmake(COMPILE_LANGUAGE-unknown-lang)
-run_cmake(COMPILE_LANGUAGE-TARGET_PROPERTY)
+run_cmake(add_custom_target)
+run_cmake(add_custom_command)
+run_cmake(install)
+run_cmake(target_sources)
+run_cmake(add_executable)
+run_cmake(add_library)
+run_cmake(add_test)
+run_cmake(unknown-lang)
+run_cmake(TARGET_PROPERTY)
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-TARGET_PROPERTY.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/TARGET_PROPERTY.cmake
index 293dddacc..293dddacc 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-TARGET_PROPERTY.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/TARGET_PROPERTY.cmake
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-stderr.txt
index 2ac9b76ac..72f0fc857 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANGUAGE-add_library.cmake:1 \(add_library\):
+CMake Error at add_custom_command.cmake:2 \(add_custom_command\):
Error evaluating generator expression:
\$<COMPILE_LANGUAGE>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command.cmake
index c3f051ab4..c3f051ab4 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command.cmake
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-stderr.txt
index 8e7f88125..a8ef8d744 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANGUAGE-target_sources.cmake:2 \(target_sources\):
+CMake Error at add_custom_target.cmake:1 \(add_custom_target\):
Error evaluating generator expression:
\$<COMPILE_LANGUAGE>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target.cmake
index b826772e2..b826772e2 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target.cmake
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-stderr.txt
index fd8a731f1..2e7cc3e62 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANGUAGE-add_test.cmake:5 \(add_test\):
+CMake Error at add_executable.cmake:1 \(add_executable\):
Error evaluating generator expression:
\$<COMPILE_LANGUAGE>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable.cmake
index ff965a9e7..ff965a9e7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-stderr.txt
index 8d05e59a0..ffbac6599 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANGUAGE-add_executable.cmake:1 \(add_executable\):
+CMake Error at add_library.cmake:1 \(add_library\):
Error evaluating generator expression:
\$<COMPILE_LANGUAGE>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library.cmake
index dd1b5a2d7..dd1b5a2d7 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-stderr.txt
new file mode 100644
index 000000000..2f13655f1
--- /dev/null
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at add_test.cmake:5 \(add_test\):
+ Error evaluating generator expression:
+
+ \$<COMPILE_LANGUAGE>
+
+ \$<COMPILE_LANGUAGE:...> may only be used to specify include directories,
+ compile definitions, compile options, and to evaluate components of the
+ file\(GENERATE\) command.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test.cmake
index deedf659e..deedf659e 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-stderr.txt
index bef7f63b9..bef7f63b9 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-stderr.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install.cmake
index 92c20e32d..92c20e32d 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-stderr.txt
new file mode 100644
index 000000000..f552e956d
--- /dev/null
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at target_sources.cmake:2 \(target_sources\):
+ Error evaluating generator expression:
+
+ \$<COMPILE_LANGUAGE>
+
+ \$<COMPILE_LANGUAGE:...> may only be used to specify include directories,
+ compile definitions, compile options, and to evaluate components of the
+ file\(GENERATE\) command.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources.cmake
index a4a5abb5e..a4a5abb5e 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources.cmake
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-unknown-lang.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/unknown-lang.cmake
index 00dd29070..00dd29070 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-unknown-lang.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/unknown-lang.cmake
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/RunCMakeTest.cmake
index 68bd05d2e..3e6e08083 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/RunCMakeTest.cmake
@@ -1,11 +1,11 @@
include(RunCMake)
-run_cmake(COMPILE_LANG_AND_ID-add_custom_target)
-run_cmake(COMPILE_LANG_AND_ID-add_custom_command)
-run_cmake(COMPILE_LANG_AND_ID-install)
-run_cmake(COMPILE_LANG_AND_ID-target_sources)
-run_cmake(COMPILE_LANG_AND_ID-add_executable)
-run_cmake(COMPILE_LANG_AND_ID-add_library)
-run_cmake(COMPILE_LANG_AND_ID-add_test)
-run_cmake(COMPILE_LANG_AND_ID-unknown-lang)
-run_cmake(COMPILE_LANG_AND_ID-TARGET_PROPERTY)
+run_cmake(add_custom_target)
+run_cmake(add_custom_command)
+run_cmake(install)
+run_cmake(target_sources)
+run_cmake(add_executable)
+run_cmake(add_library)
+run_cmake(add_test)
+run_cmake(unknown-lang)
+run_cmake(TARGET_PROPERTY)
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-TARGET_PROPERTY.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/TARGET_PROPERTY.cmake
index 6a718d64a..6a718d64a 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-TARGET_PROPERTY.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/TARGET_PROPERTY.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-stderr.txt
index 3ecbdc360..0c3c3f9f6 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANG_AND_ID-target_sources.cmake:2 \(target_sources\):
+CMake Error at add_custom_command.cmake:2 \(add_custom_command\):
Error evaluating generator expression:
\$<COMPILE_LANG_AND_ID>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command.cmake
index 9bd5e8e7e..9bd5e8e7e 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-stderr.txt
index 589e64b4e..ae85ca6c0 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANG_AND_ID-add_custom_target.cmake:2 \(add_custom_target\):
+CMake Error at add_custom_target.cmake:2 \(add_custom_target\):
Error evaluating generator expression:
\$<COMPILE_LANG_AND_ID:LANG,ID>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target.cmake
index 398db1978..398db1978 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-stderr.txt
index 4cbf000ea..ed03f204b 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANG_AND_ID-add_library.cmake:2 \(add_library\):
+CMake Error at add_executable.cmake:1 \(add_executable\):
Error evaluating generator expression:
\$<COMPILE_LANG_AND_ID:C,MSVC>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable.cmake
index 2245f5046..2245f5046 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-stderr.txt
index 3b3f38d37..0014c16c4 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANG_AND_ID-add_executable.cmake:1 \(add_executable\):
+CMake Error at add_library.cmake:2 \(add_library\):
Error evaluating generator expression:
\$<COMPILE_LANG_AND_ID:C,MSVC>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library.cmake
index 044962a53..044962a53 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-stderr.txt
index 26a5940f3..73b1a7d15 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANG_AND_ID-add_test.cmake:5 \(add_test\):
+CMake Error at add_test.cmake:5 \(add_test\):
Error evaluating generator expression:
\$<COMPILE_LANG_AND_ID:CXX,GNU>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test.cmake
index b5b6c2b82..b5b6c2b82 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-stderr.txt
index 0c4ecd091..0c4ecd091 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-stderr.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install.cmake
index c13eda6ec..c13eda6ec 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-result.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-result.txt
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-stderr.txt
index 2ee96ed14..ea6fbbf44 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANG_AND_ID-add_custom_command.cmake:2 \(add_custom_command\):
+CMake Error at target_sources.cmake:2 \(target_sources\):
Error evaluating generator expression:
\$<COMPILE_LANG_AND_ID>
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources.cmake
index a2c9b03f5..a2c9b03f5 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources.cmake
diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-unknown-lang.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/unknown-lang.cmake
index b9e840b41..b9e840b41 100644
--- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-unknown-lang.cmake
+++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/unknown-lang.cmake
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake
index 80633e258..1ce98f0fd 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake
@@ -1,18 +1,18 @@
include(RunCMake)
-run_cmake(DEVICE_LINK-add_custom_target)
-run_cmake(DEVICE_LINK-add_custom_command)
-run_cmake(DEVICE_LINK-install)
-run_cmake(DEVICE_LINK-add_executable)
-run_cmake(DEVICE_LINK-add_library)
-run_cmake(DEVICE_LINK-add_test)
-run_cmake(DEVICE_LINK-target_sources)
-run_cmake(DEVICE_LINK-target_compile_definitions)
-run_cmake(DEVICE_LINK-target_compile_options)
-run_cmake(DEVICE_LINK-target_include_directories)
-run_cmake(DEVICE_LINK-target_link_libraries)
-run_cmake(DEVICE_LINK-target_link_directories)
-run_cmake(DEVICE_LINK-try_compile)
+run_cmake(add_custom_target)
+run_cmake(add_custom_command)
+run_cmake(install)
+run_cmake(add_executable)
+run_cmake(add_library)
+run_cmake(add_test)
+run_cmake(target_sources)
+run_cmake(target_compile_definitions)
+run_cmake(target_compile_options)
+run_cmake(target_include_directories)
+run_cmake(target_link_libraries)
+run_cmake(target_link_directories)
+run_cmake(try_compile)
if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)")
- run_cmake(DEVICE_LINK-link_depends)
+ run_cmake(link_depends)
endif()
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-stderr.txt
index cdd3043a2..273c3b2be 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-add_custom_target.cmake:[0-9]+ \(add_custom_target\):
+CMake Error at add_custom_command.cmake:[0-9]+ \(add_custom_command\):
Error evaluating generator expression:
\$<DEVICE_LINK>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command.cmake
index 01b378493..01b378493 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-stderr.txt
index eb15834c5..0c015fa6f 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-add_custom_command.cmake:[0-9]+ \(add_custom_command\):
+CMake Error at add_custom_target.cmake:[0-9]+ \(add_custom_target\):
Error evaluating generator expression:
\$<DEVICE_LINK>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target.cmake
index 35728e9c0..35728e9c0 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-stderr.txt
index 4477e00ae..3d5bfb372 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-add_library.cmake:[0-9]+ \(add_library\):
+CMake Error at add_executable.cmake:[0-9]+ \(add_executable\):
Error evaluating generator expression:
\$<DEVICE_LINK:empty.c>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable.cmake
index 899f8f68a..899f8f68a 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library-stderr.txt
index c9b602d84..5b8448b69 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-target_sources.cmake:[0-9]+ \(target_sources\):
+CMake Error at add_library.cmake:[0-9]+ \(add_library\):
Error evaluating generator expression:
\$<DEVICE_LINK:empty.c>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library.cmake
index fc8547b60..fc8547b60 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test-stderr.txt
index 99561fe2c..56f8ce7e6 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-add_test.cmake:[0-9]+ \(add_test\):
+CMake Error at add_test.cmake:[0-9]+ \(add_test\):
Error evaluating generator expression:
\$<DEVICE_LINK>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test.cmake
index 87d6ba16d..87d6ba16d 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/install-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/install-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/install-stderr.txt
index afb3090ad..afb3090ad 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/install-stderr.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/install.cmake
index 4b6dbef28..4b6dbef28 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/install.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-stderr.txt
index 4fa0522b0..4fa0522b0 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-stderr.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/link_depends.cmake
index 8129514a4..8129514a4 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/link_depends.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-stderr.txt
index c0185e3a7..e6bd546a4 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-target_compile_definitions.cmake:[0-9]+ \(target_compile_definitions\):
+CMake Error at target_compile_definitions.cmake:[0-9]+ \(target_compile_definitions\):
Error evaluating generator expression:
\$<DEVICE_LINK:DEF>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions.cmake
index aaa8efc1f..aaa8efc1f 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-stderr.txt
index 34ca4f236..31e0eca5c 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-target_compile_options.cmake:[0-9]+ \(target_compile_options\):
+CMake Error at target_compile_options.cmake:[0-9]+ \(target_compile_options\):
Error evaluating generator expression:
\$<DEVICE_LINK:-OPT>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options.cmake
index a9cb7fd4d..a9cb7fd4d 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-stderr.txt
index d924916a5..b104e1bee 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-target_link_directories.cmake:[0-9]+ \(target_link_directories\):
+CMake Error at target_include_directories.cmake:[0-9]+ \(target_include_directories\):
Error evaluating generator expression:
\$<DEVICE_LINK:/DIR>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories.cmake
index 03cc413e8..03cc413e8 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-stderr.txt
index 4d1642d78..a2f9c52d6 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-target_include_directories.cmake:[0-9]+ \(target_include_directories\):
+CMake Error at target_link_directories.cmake:[0-9]+ \(target_link_directories\):
Error evaluating generator expression:
\$<DEVICE_LINK:/DIR>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories.cmake
index e50d27d89..e50d27d89 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-stderr.txt
index 1436fa8fe..ce2aeee24 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-target_link_libraries.cmake:[0-9]+ \(target_link_libraries\):
+CMake Error at target_link_libraries.cmake:[0-9]+ \(target_link_libraries\):
Error evaluating generator expression:
\$<DEVICE_LINK:lib>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries.cmake
index 971f56206..971f56206 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-result.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-result.txt
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-stderr.txt
index 56b595c74..341b0f885 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-stderr.txt
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at DEVICE_LINK-add_executable.cmake:[0-9]+ \(add_executable\):
+CMake Error at target_sources.cmake:[0-9]+ \(target_sources\):
Error evaluating generator expression:
\$<DEVICE_LINK:empty.c>
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources.cmake
index 94bac9e2c..94bac9e2c 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources.cmake
diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-try_compile.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/try_compile.cmake
index 281f8aa3a..281f8aa3a 100644
--- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-try_compile.cmake
+++ b/Tests/RunCMake/GenEx-DEVICE_LINK/try_compile.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake
index 9e3eeec41..1ce98f0fd 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake
@@ -1,18 +1,18 @@
include(RunCMake)
-run_cmake(HOST_LINK-add_custom_target)
-run_cmake(HOST_LINK-add_custom_command)
-run_cmake(HOST_LINK-install)
-run_cmake(HOST_LINK-add_executable)
-run_cmake(HOST_LINK-add_library)
-run_cmake(HOST_LINK-add_test)
-run_cmake(HOST_LINK-target_sources)
-run_cmake(HOST_LINK-target_compile_definitions)
-run_cmake(HOST_LINK-target_compile_options)
-run_cmake(HOST_LINK-target_include_directories)
-run_cmake(HOST_LINK-target_link_libraries)
-run_cmake(HOST_LINK-target_link_directories)
-run_cmake(HOST_LINK-try_compile)
+run_cmake(add_custom_target)
+run_cmake(add_custom_command)
+run_cmake(install)
+run_cmake(add_executable)
+run_cmake(add_library)
+run_cmake(add_test)
+run_cmake(target_sources)
+run_cmake(target_compile_definitions)
+run_cmake(target_compile_options)
+run_cmake(target_include_directories)
+run_cmake(target_link_libraries)
+run_cmake(target_link_directories)
+run_cmake(try_compile)
if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)")
- run_cmake(HOST_LINK-link_depends)
+ run_cmake(link_depends)
endif()
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-stderr.txt
index c44202a70..0eb5e3388 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-add_custom_target.cmake:[0-9]+ \(add_custom_target\):
+CMake Error at add_custom_command.cmake:[0-9]+ \(add_custom_command\):
Error evaluating generator expression:
\$<HOST_LINK>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command.cmake
index 4d6e30531..4d6e30531 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-stderr.txt
index 5ad41b96d..ffb0c3dcd 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-add_custom_command.cmake:[0-9]+ \(add_custom_command\):
+CMake Error at add_custom_target.cmake:[0-9]+ \(add_custom_target\):
Error evaluating generator expression:
\$<HOST_LINK>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target.cmake
index eec072a96..eec072a96 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_executable-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_executable-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_executable-stderr.txt
index 4bd27bec9..59732d8d0 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_executable-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-add_library.cmake:[0-9]+ \(add_library\):
+CMake Error at add_executable.cmake:[0-9]+ \(add_executable\):
Error evaluating generator expression:
\$<HOST_LINK:empty.c>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_executable.cmake
index c9f74a5c0..c9f74a5c0 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_executable.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_library-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_library-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_library-stderr.txt
index 0e2556812..4e9fea10b 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_library-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-target_sources.cmake:[0-9]+ \(target_sources\):
+CMake Error at add_library.cmake:[0-9]+ \(add_library\):
Error evaluating generator expression:
\$<HOST_LINK:empty.c>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_library.cmake
index 44135af00..44135af00 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_library.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_test-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_test-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_test-stderr.txt
index 012ad210a..11912ddee 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_test-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-add_test.cmake:[0-9]+ \(add_test\):
+CMake Error at add_test.cmake:[0-9]+ \(add_test\):
Error evaluating generator expression:
\$<HOST_LINK>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_test.cmake
index 4b472afe4..4b472afe4 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/add_test.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/install-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/install-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/install-stderr.txt
index c265ec418..c265ec418 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/install-stderr.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install.cmake b/Tests/RunCMake/GenEx-HOST_LINK/install.cmake
index b4dff680e..b4dff680e 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/install.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/link_depends-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/link_depends-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/link_depends-stderr.txt
index 24b8b82f4..24b8b82f4 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/link_depends-stderr.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends.cmake b/Tests/RunCMake/GenEx-HOST_LINK/link_depends.cmake
index 0402f43e8..0402f43e8 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/link_depends.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-stderr.txt
index 6ab3c14d8..09982e108 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-target_compile_definitions.cmake:[0-9]+ \(target_compile_definitions\):
+CMake Error at target_compile_definitions.cmake:[0-9]+ \(target_compile_definitions\):
Error evaluating generator expression:
\$<HOST_LINK:DEF>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions.cmake
index f6c130d40..f6c130d40 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-stderr.txt
index 0f5bbc38c..42ff6635f 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-target_compile_options.cmake:[0-9]+ \(target_compile_options\):
+CMake Error at target_compile_options.cmake:[0-9]+ \(target_compile_options\):
Error evaluating generator expression:
\$<HOST_LINK:-OPT>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options.cmake
index 53afea19e..53afea19e 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-stderr.txt
index 5225a5253..1c83da307 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-target_link_directories.cmake:[0-9]+ \(target_link_directories\):
+CMake Error at target_include_directories.cmake:[0-9]+ \(target_include_directories\):
Error evaluating generator expression:
\$<HOST_LINK:/DIR>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories.cmake
index aff100923..aff100923 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-stderr.txt
index 9a2634a22..0b5401809 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-target_include_directories.cmake:[0-9]+ \(target_include_directories\):
+CMake Error at target_link_directories.cmake:[0-9]+ \(target_link_directories\):
Error evaluating generator expression:
\$<HOST_LINK:/DIR>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories.cmake
index 97488eef8..97488eef8 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-result.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-result.txt
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-stderr.txt
index 6c4441f3c..bf46e3ad4 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-target_link_libraries.cmake:[0-9]+ \(target_link_libraries\):
+CMake Error at target_link_libraries.cmake:[0-9]+ \(target_link_libraries\):
Error evaluating generator expression:
\$<HOST_LINK:lib>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries.cmake
index d74c92d4b..d74c92d4b 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/target_sources-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_sources-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_sources-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_sources-stderr.txt
index b39551577..547c2e544 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-stderr.txt
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_sources-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at HOST_LINK-add_executable.cmake:[0-9]+ \(add_executable\):
+CMake Error at target_sources.cmake:[0-9]+ \(target_sources\):
Error evaluating generator expression:
\$<HOST_LINK:empty.c>
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_sources.cmake
index ea7bf551d..ea7bf551d 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/target_sources.cmake
diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-try_compile.cmake b/Tests/RunCMake/GenEx-HOST_LINK/try_compile.cmake
index f221ff1b6..f221ff1b6 100644
--- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-try_compile.cmake
+++ b/Tests/RunCMake/GenEx-HOST_LINK/try_compile.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-stderr.txt
deleted file mode 100644
index 0b0d458fd..000000000
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-stderr.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-CMake Error at LINK_LANGUAGE-add_custom_command.cmake:2 \(add_custom_command\):
- Error evaluating generator expression:
-
- \$<LINK_LANGUAGE>
-
- \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
- libraries, link directories, link options and link depends.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-stderr.txt
deleted file mode 100644
index 92da63454..000000000
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-stderr.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-CMake Error at LINK_LANGUAGE-add_custom_target.cmake:1 \(add_custom_target\):
- Error evaluating generator expression:
-
- \$<LINK_LANGUAGE>
-
- \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
- libraries, link directories, link options and link depends.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-stderr.txt
deleted file mode 100644
index d8121cce6..000000000
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-stderr.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-CMake Error at LINK_LANGUAGE-target_sources.cmake:2 \(target_sources\):
- Error evaluating generator expression:
-
- \$<LINK_LANGUAGE>
-
- \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
- libraries, link directories, link options and link depends.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/RunCMakeTest.cmake
index 4cf0c047d..53320ac5a 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/RunCMakeTest.cmake
@@ -1,15 +1,15 @@
include(RunCMake)
-run_cmake(LINK_LANGUAGE-add_custom_target)
-run_cmake(LINK_LANGUAGE-add_custom_command)
-run_cmake(LINK_LANGUAGE-install)
-run_cmake(LINK_LANGUAGE-target_sources)
-run_cmake(LINK_LANGUAGE-add_executable)
-run_cmake(LINK_LANGUAGE-add_library)
-run_cmake(LINK_LANGUAGE-add_test)
-run_cmake(LINK_LANGUAGE-unknown-lang)
-run_cmake(LINK_LANGUAGE-wrong-usage1)
-run_cmake(LINK_LANGUAGE-wrong-usage2)
-run_cmake(LINK_LANGUAGE-wrong-usage3)
-run_cmake(LINK_LANGUAGE-wrong-usage4)
-run_cmake(LINK_LANGUAGE-file_generate)
+run_cmake(add_custom_target)
+run_cmake(add_custom_command)
+run_cmake(install)
+run_cmake(target_sources)
+run_cmake(add_executable)
+run_cmake(add_library)
+run_cmake(add_test)
+run_cmake(unknown-lang)
+run_cmake(wrong-usage1)
+run_cmake(wrong-usage2)
+run_cmake(wrong-usage3)
+run_cmake(wrong-usage4)
+run_cmake(file_generate)
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-stderr.txt
index 1bacdeb4c..2ac7add76 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANGUAGE-add_library.cmake:1 \(add_library\):
+CMake Error at add_custom_command.cmake:2 \(add_custom_command\):
Error evaluating generator expression:
\$<LINK_LANGUAGE>
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command.cmake
index a378c1c0d..a378c1c0d 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-stderr.txt
index 3bdc8e493..5e54baefd 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANGUAGE-add_executable.cmake:1 \(add_executable\):
+CMake Error at add_custom_target.cmake:1 \(add_custom_target\):
Error evaluating generator expression:
\$<LINK_LANGUAGE>
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target.cmake
index 60b6c75f2..60b6c75f2 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-stderr.txt
index f22efde7e..06c00fcfe 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANGUAGE-add_test.cmake:5 \(add_test\):
+CMake Error at add_executable.cmake:1 \(add_executable\):
Error evaluating generator expression:
\$<LINK_LANGUAGE>
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable.cmake
index 2176b3923..2176b3923 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-stderr.txt
index 21d26de5f..6e312a14e 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANGUAGE-file_generate.cmake:3 \(file\):
+CMake Error at add_library.cmake:1 \(add_library\):
Error evaluating generator expression:
\$<LINK_LANGUAGE>
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library.cmake
index 253f82a36..253f82a36 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-stderr.txt
new file mode 100644
index 000000000..3deb92326
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-stderr.txt
@@ -0,0 +1,9 @@
+CMake Error at add_test.cmake:5 \(add_test\):
+ Error evaluating generator expression:
+
+ \$<LINK_LANGUAGE>
+
+ \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
+ libraries, link directories, link options and link depends.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test.cmake
index 4fd547d54..4fd547d54 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-stderr.txt
new file mode 100644
index 000000000..0e3d6814e
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-stderr.txt
@@ -0,0 +1,9 @@
+CMake Error at file_generate.cmake:3 \(file\):
+ Error evaluating generator expression:
+
+ \$<LINK_LANGUAGE>
+
+ \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
+ libraries, link directories, link options and link depends.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate.cmake
index 519b883c4..519b883c4 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/install-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/install-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/install-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/install-stderr.txt
index 73afc3377..73afc3377 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/install-stderr.txt
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/install.cmake
index 533c0b459..533c0b459 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/install.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-stderr.txt
new file mode 100644
index 000000000..4c63a6e6c
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-stderr.txt
@@ -0,0 +1,9 @@
+CMake Error at target_sources.cmake:2 \(target_sources\):
+ Error evaluating generator expression:
+
+ \$<LINK_LANGUAGE>
+
+ \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
+ libraries, link directories, link options and link depends.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources.cmake
index c134c0197..c134c0197 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-unknown-lang.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/unknown-lang.cmake
index 0ba472d7b..0ba472d7b 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-unknown-lang.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/unknown-lang.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-stderr.txt
index 7fe43101b..58562b3b7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANGUAGE-wrong-usage2.cmake:4 \(target_compile_options\):
+CMake Error at wrong-usage1.cmake:4 \(target_compile_definitions\):
Error evaluating generator expression:
\$<LINK_LANGUAGE:C>
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1.cmake
index 90b7ce033..90b7ce033 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-stderr.txt
index cb20e996d..46fbc6749 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANGUAGE-wrong-usage3.cmake:4 \(target_include_directories\):
+CMake Error at wrong-usage2.cmake:4 \(target_compile_options\):
Error evaluating generator expression:
\$<LINK_LANGUAGE:C>
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2.cmake
index e761897ed..e761897ed 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-stderr.txt
index 1e3a83b92..2cabc9048 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANGUAGE-wrong-usage1.cmake:4 \(target_compile_definitions\):
+CMake Error at wrong-usage3.cmake:4 \(target_include_directories\):
Error evaluating generator expression:
\$<LINK_LANGUAGE:C>
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3.cmake
index 96a72a188..96a72a188 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-stderr.txt
index ee36912df..367976004 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANGUAGE-wrong-usage4.cmake:7 \(target_link_libraries\):
+CMake Error at wrong-usage4.cmake:7 \(target_link_libraries\):
Error evaluating generator expression:
\$<LINK_LANGUAGE>
diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4.cmake
index 3ecaabbe4..3ecaabbe4 100644
--- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake
index 5bb6590a6..74a179c25 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake
@@ -1,14 +1,14 @@
include(RunCMake)
-run_cmake(LINK_LANG_AND_ID-add_custom_target)
-run_cmake(LINK_LANG_AND_ID-add_custom_command)
-run_cmake(LINK_LANG_AND_ID-install)
-run_cmake(LINK_LANG_AND_ID-target_sources)
-run_cmake(LINK_LANG_AND_ID-add_executable)
-run_cmake(LINK_LANG_AND_ID-add_library)
-run_cmake(LINK_LANG_AND_ID-add_test)
-run_cmake(LINK_LANG_AND_ID-unknown-lang)
-run_cmake(LINK_LANG_AND_ID-wrong-usage1)
-run_cmake(LINK_LANG_AND_ID-wrong-usage2)
-run_cmake(LINK_LANG_AND_ID-wrong-usage3)
-run_cmake(LINK_LANG_AND_ID-file_generate)
+run_cmake(add_custom_target)
+run_cmake(add_custom_command)
+run_cmake(install)
+run_cmake(target_sources)
+run_cmake(add_executable)
+run_cmake(add_library)
+run_cmake(add_test)
+run_cmake(unknown-lang)
+run_cmake(wrong-usage1)
+run_cmake(wrong-usage2)
+run_cmake(wrong-usage3)
+run_cmake(file_generate)
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-stderr.txt
index 0749c449a..412e3adb2 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-add_custom_target.cmake:2 \(add_custom_target\):
+CMake Error at add_custom_command.cmake:2 \(add_custom_command\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID:LANG,ID>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command.cmake
index 9df923232..9df923232 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-stderr.txt
index 2ff62bc42..a927b208a 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-add_custom_command.cmake:2 \(add_custom_command\):
+CMake Error at add_custom_target.cmake:2 \(add_custom_target\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID:LANG,ID>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target.cmake
index e5f76bcd1..e5f76bcd1 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-stderr.txt
index be46e287a..c58cbdf12 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-add_library.cmake:2 \(add_library\):
+CMake Error at add_executable.cmake:1 \(add_executable\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID:C,MSVC>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable.cmake
index 4d6c67482..4d6c67482 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-stderr.txt
index 595312a72..46a32d020 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-add_executable.cmake:1 \(add_executable\):
+CMake Error at add_library.cmake:2 \(add_library\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID:C,MSVC>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library.cmake
index a8199cf86..a8199cf86 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-stderr.txt
index 2a29492e8..989329868 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-add_test.cmake:5 \(add_test\):
+CMake Error at add_test.cmake:5 \(add_test\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID:CXX,GNU>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test.cmake
index fd700d796..fd700d796 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-stderr.txt
index e57b55c1c..fa05f8d90 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-file_generate.cmake:3 \(file\):
+CMake Error at file_generate.cmake:3 \(file\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID:C,GNU>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate.cmake
index 67c1bdacd..67c1bdacd 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-stderr.txt
index 965f974cb..965f974cb 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-stderr.txt
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install.cmake
index b8f93233c..b8f93233c 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-stderr.txt
index e86602a0f..aecf1245b 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-target_sources.cmake:2 \(target_sources\):
+CMake Error at target_sources.cmake:2 \(target_sources\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources.cmake
index da5faf490..da5faf490 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-unknown-lang.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/unknown-lang.cmake
index 99dd33760..99dd33760 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-unknown-lang.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/unknown-lang.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-stderr.txt
index 53bdcb2a5..729cc2f1a 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-wrong-usage2.cmake:4 \(target_compile_options\):
+CMake Error at wrong-usage1.cmake:4 \(target_compile_definitions\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID:C,GNU>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1.cmake
index e58e3b449..e58e3b449 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-stderr.txt
index a34a2ea57..786c16d1c 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-wrong-usage3.cmake:4 \(target_include_directories\):
+CMake Error at wrong-usage2.cmake:4 \(target_compile_options\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID:C,GNU>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2.cmake
index 998daa9b7..998daa9b7 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2.cmake
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-stderr.txt
index 95611c310..31679a125 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at LINK_LANG_AND_ID-wrong-usage1.cmake:4 \(target_compile_definitions\):
+CMake Error at wrong-usage3.cmake:4 \(target_include_directories\):
Error evaluating generator expression:
\$<LINK_LANG_AND_ID:C,GNU>
diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3.cmake
index 054305638..054305638 100644
--- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3.cmake
diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake
index 40f7c66f2..7eec527c8 100644
--- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake
+++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake
@@ -58,8 +58,8 @@ set_property (TARGET static3 PROPERTY ARCHIVE_OUTPUT_NAME static3_archive)
string (APPEND GENERATE_CONTENT [[
check_value ("TARGET_FILE_BASE_NAME executable all properties" "$<TARGET_FILE_BASE_NAME:exec3>" "exec3_runtime")
-check_value ("TARGET_FILE_BASE_NAME shared all properties" "$<TARGET_FILE_BASE_NAME:shared3>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN>,shared3_runtime,shared3_library>")
-check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties" "$<TARGET_LINKER_FILE_BASE_NAME:shared3>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN>,shared3_archive,shared3_library>")
+check_value ("TARGET_FILE_BASE_NAME shared all properties" "$<TARGET_FILE_BASE_NAME:shared3>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared3_runtime,shared3_library>")
+check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties" "$<TARGET_LINKER_FILE_BASE_NAME:shared3>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared3_archive,shared3_library>")
check_value ("TARGET_FILE_BASE_NAME static all properties" "$<TARGET_FILE_BASE_NAME:static3>" "static3_archive")
check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties" "$<TARGET_LINKER_FILE_BASE_NAME:static3>" "static3_archive")
]])
@@ -95,8 +95,8 @@ set_property (TARGET static4 PROPERTY ${FIRST_CONFIG}_POSTFIX _postfix)
string (APPEND GENERATE_CONTENT [[
check_value ("TARGET_FILE_BASE_NAME executable all properties + postfix" "$<TARGET_FILE_BASE_NAME:exec4>" "exec4_runtime_postfix")
-check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$<TARGET_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN>,shared4_runtime,shared4_library>_postfix")
-check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN>,shared4_archive,shared4_library>_postfix")
+check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$<TARGET_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_runtime,shared4_library>_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_archive,shared4_library>_postfix")
check_value ("TARGET_FILE_BASE_NAME static all properties + postfix" "$<TARGET_FILE_BASE_NAME:static4>" "static4_archive_postfix")
check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:static4>" "static4_archive_postfix")
]])
diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake
index f88d7109a..1963244fa 100644
--- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake
+++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake
@@ -72,8 +72,8 @@ set_property (TARGET static3 PROPERTY PDB_NAME static3_pdb)
string (APPEND GENERATE_CONTENT [[
check_value ("TARGET_FILE_BASE_NAME executable all properties" "$<TARGET_FILE_BASE_NAME:exec3>" "exec3_runtime")
-check_value ("TARGET_FILE_BASE_NAME shared all properties" "$<TARGET_FILE_BASE_NAME:shared3>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN>,shared3_runtime,shared3_library>")
-check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties" "$<TARGET_LINKER_FILE_BASE_NAME:shared3>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN>,shared3_archive,shared3_library>")
+check_value ("TARGET_FILE_BASE_NAME shared all properties" "$<TARGET_FILE_BASE_NAME:shared3>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared3_runtime,shared3_library>")
+check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties" "$<TARGET_LINKER_FILE_BASE_NAME:shared3>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared3_archive,shared3_library>")
check_value ("TARGET_FILE_BASE_NAME static all properties" "$<TARGET_FILE_BASE_NAME:static3>" "static3_archive")
check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties" "$<TARGET_LINKER_FILE_BASE_NAME:static3>" "static3_archive")
]])
@@ -118,8 +118,8 @@ set_property (TARGET static4 PROPERTY ${FIRST_CONFIG}_POSTFIX _postfix)
string (APPEND GENERATE_CONTENT [[
check_value ("TARGET_FILE_BASE_NAME executable all properties + postfix" "$<TARGET_FILE_BASE_NAME:exec4>" "exec4_runtime_postfix")
-check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$<TARGET_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN>,shared4_runtime,shared4_library>_postfix")
-check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN>,shared4_archive,shared4_library>_postfix")
+check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$<TARGET_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_runtime,shared4_library>_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_archive,shared4_library>_postfix")
check_value ("TARGET_FILE_BASE_NAME static all properties + postfix" "$<TARGET_FILE_BASE_NAME:static4>" "static4_archive_postfix")
check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:static4>" "static4_archive_postfix")
]])
diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX-imported-target.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX-imported-target.cmake
index f52776e98..cc9cd5a8f 100644
--- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX-imported-target.cmake
+++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX-imported-target.cmake
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
enable_language (C)
-set (win_platforms Windows CYGWIN)
+set (win_platforms Windows CYGWIN MSYS)
set (GENERATE_CONTENT [[
macro (CHECK_VALUE test_msg value expected)
diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX.cmake
index bef7bbf5c..edfb40c53 100644
--- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX.cmake
+++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX.cmake
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
enable_language (C)
-set (win_platforms Windows CYGWIN)
+set (win_platforms Windows CYGWIN MSYS)
set (GENERATE_CONTENT [[
macro (CHECK_VALUE test_msg value expected)
diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX-imported-target.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX-imported-target.cmake
index cefeb86f1..3ee42a5c1 100644
--- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX-imported-target.cmake
+++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX-imported-target.cmake
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
enable_language (C)
-set (win_platforms Windows CYGWIN)
+set (win_platforms Windows CYGWIN MSYS)
set (GENERATE_CONTENT [[
macro (CHECK_VALUE test_msg value expected)
diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX.cmake
index 39e39fd5b..1fe75d951 100644
--- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX.cmake
+++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX.cmake
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
enable_language (C)
-set (win_platforms Windows CYGWIN)
+set (win_platforms Windows CYGWIN MSYS)
set (GENERATE_CONTENT [[
macro (CHECK_VALUE test_msg value expected)
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/CMakeLists.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/CMakeLists.txt
new file mode 100644
index 000000000..ab1a20c7e
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.19)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake
new file mode 100644
index 000000000..a48b525bb
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake
@@ -0,0 +1,7 @@
+include(RunCMake)
+
+run_cmake(shared)
+run_cmake(static)
+run_cmake(target_link_libraries)
+run_cmake(target_link_libraries-cycle1)
+run_cmake(target_link_libraries-cycle2)
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake
new file mode 100644
index 000000000..e19598e14
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake
@@ -0,0 +1,15 @@
+function(check_genex expected actual)
+ if(NOT expected STREQUAL actual)
+ string(APPEND RunCMake_TEST_FAILED "Expected DLLs:\n")
+ foreach(dll IN LISTS expected)
+ string(APPEND RunCMake_TEST_FAILED " ${dll}\n")
+ endforeach()
+ string(APPEND RunCMake_TEST_FAILED "Actual DLLs:\n")
+ foreach(dll IN LISTS actual)
+ string(APPEND RunCMake_TEST_FAILED " ${dll}\n")
+ endforeach()
+ endif()
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction()
+
+include("${RunCMake_TEST_BINARY_DIR}/dlls.cmake")
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib1.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib1.c
new file mode 100644
index 000000000..524b5b22f
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib1.c
@@ -0,0 +1,12 @@
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ extern void lib2(void);
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void lib1(void)
+{
+ lib2();
+}
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib2.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib2.c
new file mode 100644
index 000000000..e14511747
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib2.c
@@ -0,0 +1,6 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void lib2(void)
+{
+}
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib3.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib3.c
new file mode 100644
index 000000000..5392f7a3c
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib3.c
@@ -0,0 +1,6 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void lib3(void)
+{
+}
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/main.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/main.c
new file mode 100644
index 000000000..8488f4e58
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/main.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake
new file mode 100644
index 000000000..806f0b60f
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake
@@ -0,0 +1,37 @@
+enable_language(C)
+
+add_executable(exe main.c)
+add_library(lib1 SHARED lib1.c)
+add_library(lib2 SHARED lib2.c)
+add_library(lib3 SHARED lib3.c)
+add_library(static STATIC static.c)
+add_library(imported SHARED IMPORTED)
+set_property(TARGET imported PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/imported.dll")
+set_property(TARGET imported PROPERTY IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/imported.lib")
+add_library(imported2 SHARED IMPORTED)
+if(NOT WIN32 AND NOT CYGWIN)
+ set_property(TARGET imported2 PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/imported2.dll")
+endif()
+set_property(TARGET imported2 PROPERTY IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/imported2.lib")
+
+target_link_libraries(exe PRIVATE lib1 static imported imported2)
+target_link_libraries(lib1 PRIVATE lib2)
+target_link_libraries(lib1 INTERFACE lib3)
+
+set(expected_dlls "")
+if(WIN32 OR CYGWIN)
+ set(expected_dlls
+ "$<TARGET_FILE:lib1>"
+ "$<TARGET_FILE:imported>"
+ "$<TARGET_FILE:lib3>"
+ "$<TARGET_FILE:lib2>"
+ )
+endif()
+
+set(content "check_genex(\"${expected_dlls}\" \"$<TARGET_RUNTIME_DLLS:exe>\")\n")
+set(condition)
+get_property(multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(multi_config)
+ set(condition CONDITION "$<CONFIG:Debug>")
+endif()
+file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/dlls.cmake" CONTENT "${content}" ${condition})
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-result.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-stderr.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-stderr.txt
new file mode 100644
index 000000000..af68c9689
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-stderr.txt
@@ -0,0 +1,9 @@
+CMake Error at static\.cmake:[0-9]+ \(file\):
+ Error evaluating generator expression:
+
+ \$<TARGET_RUNTIME_DLLS:static>
+
+ Objects of target "static" referenced but is not one of the allowed target
+ types \(EXECUTABLE, SHARED, MODULE\)\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.c
new file mode 100644
index 000000000..7f5dab50a
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.c
@@ -0,0 +1,3 @@
+void static_func(void)
+{
+}
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.cmake
new file mode 100644
index 000000000..dc900ddf1
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+
+add_library(static STATIC static.c)
+set(condition)
+get_property(multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(multi_config)
+ set(condition CONDITION "$<CONFIG:Debug>")
+endif()
+file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/dlls.txt" CONTENT "$<TARGET_RUNTIME_DLLS:static>" ${condition})
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-result.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-stderr.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-stderr.txt
new file mode 100644
index 000000000..b6ae09941
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at target_link_libraries-cycle1\.cmake:[0-9]+ \(add_library\):
+ The SOURCES of "lib1" use a generator expression that depends on the
+ SOURCES themselves\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1.cmake
new file mode 100644
index 000000000..f19e9e6a7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1.cmake
@@ -0,0 +1,4 @@
+enable_language(C)
+
+add_library(lib1 SHARED lib1.c)
+target_link_libraries(lib1 PRIVATE $<TARGET_RUNTIME_DLLS:lib1>)
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-result.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-stderr.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-stderr.txt
new file mode 100644
index 000000000..9a845f967
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at target_link_libraries-cycle2\.cmake:[0-9]+ \(add_library\):
+ The SOURCES of "(lib1|lib2)" use a generator expression that depends on the
+ SOURCES themselves\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2.cmake
new file mode 100644
index 000000000..7d035bd87
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+add_library(lib1 SHARED lib1.c)
+add_library(lib2 SHARED lib2.c)
+target_link_libraries(lib1 PRIVATE $<TARGET_RUNTIME_DLLS:lib2>)
+target_link_libraries(lib2 PRIVATE $<TARGET_RUNTIME_DLLS:lib1>)
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries.cmake
new file mode 100644
index 000000000..f44dbf4b1
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries.cmake
@@ -0,0 +1,5 @@
+enable_language(C)
+
+add_library(lib1 SHARED lib1.c)
+add_library(lib2 SHARED lib2.c)
+target_link_libraries(lib1 PRIVATE $<TARGET_RUNTIME_DLLS:lib2>)
diff --git a/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp b/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp
index dcaa4f2d1..2cfcd8dea 100644
--- a/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp
+++ b/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp
@@ -8,6 +8,14 @@
#include "libshared.h"
#include "libstatic.h"
+static void rtrim(std::string& str, char byte)
+{
+ size_t const size = str.size();
+ if (size && str[size - 1] == byte) {
+ str.resize(size - 1);
+ }
+}
+
void compare(const char* refName, const char* testName)
{
std::ifstream ref;
@@ -31,16 +39,14 @@ void compare(const char* refName, const char* testName)
// Some very old Borland runtimes (C++ Builder 5 WITHOUT Update 1) add a
// trailing null to the string that we need to strip before testing for a
// trailing space.
- if (refLine.size() && refLine[refLine.size() - 1] == 0) {
- refLine.resize(refLine.size() - 1);
- }
- if (testLine.size() && testLine[testLine.size() - 1] == 0) {
- testLine.resize(testLine.size() - 1);
- }
+ rtrim(refLine, 0);
+ rtrim(testLine, 0);
// The reference files never have trailing spaces:
- if (testLine.size() && testLine[testLine.size() - 1] == ' ') {
- testLine.resize(testLine.size() - 1);
- }
+ rtrim(testLine, ' ');
+ // Strip trailing CR. LF is not returned by getline, but CR is returned
+ // on some platforms.
+ rtrim(refLine, '\r');
+ rtrim(testLine, '\r');
if (refLine != testLine) {
std::cout << "Ref and test are not the same:\n Ref: \"" << refLine
<< "\"\n Test: \"" << testLine << "\"\n";
diff --git a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake
index 27ede066e..a7519c373 100644
--- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake
@@ -3,7 +3,7 @@ include(RunCMake)
set(RunCMake_GENERATOR_PLATFORM "")
run_cmake(NoPlatform)
-if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[012456])( 20[0-9][0-9])?$")
+if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[0124567])( 20[0-9][0-9])?$")
set(RunCMake_GENERATOR_PLATFORM "x64")
run_cmake(x64Platform)
else()
@@ -11,13 +11,13 @@ else()
run_cmake(BadPlatform)
endif()
-set(RunCMake_GENERATOR_TOOLSET "")
+set(RunCMake_GENERATOR_PLATFORM "")
-set(RunCMake_TEST_OPTIONS -A "Extra Platform")
+set(RunCMake_TEST_OPTIONS -A "Test Platform" -A "Extra Platform")
run_cmake(TwoPlatforms)
unset(RunCMake_TEST_OPTIONS)
-if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[012456])( 20[0-9][0-9])?$")
+if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[0124567])( 20[0-9][0-9])?$")
set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestPlatform-toolchain.cmake)
run_cmake(TestPlatformToolchain)
unset(RunCMake_TEST_OPTIONS)
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-stderr.txt
new file mode 100644
index 000000000..d8b6c5eab
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-stderr.txt
@@ -0,0 +1,11 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+ Generator
+
+ Visual Studio [^
+]*
+
+ given toolset
+
+ customFlagTableDir=does_not_exist
+
+ that is not an absolute path to an existing directory.$
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir.cmake
new file mode 100644
index 000000000..2fc38e5c5
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt
index 5e88e3bf1..ba7a8f311 100644
--- a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt
@@ -7,4 +7,4 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\):
buildsystem=bad
- value is unkonwn. It must be '1' or '12'\.$
+ value is unknown. It must be '1' or '12'\.$
diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
index 5f12d799a..a7423918f 100644
--- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
@@ -1,9 +1,15 @@
include(RunCMake)
+if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[0124567]")
+ run_cmake(VsNormal)
+ include("${RunCMake_BINARY_DIR}/VsNormal-build/defaults.cmake" OPTIONAL)
+ message(STATUS "VsNormal: platform='${VsNormal_Platform}' toolset='${VsNormal_Toolset}'")
+endif()
+
set(RunCMake_GENERATOR_TOOLSET "")
run_cmake(NoToolset)
-if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]")
+if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[0124567]")
set(RunCMake_GENERATOR_TOOLSET "Test Toolset")
run_cmake(TestToolset)
set(RunCMake_GENERATOR_TOOLSET "Test Toolset,cuda=0.0")
@@ -12,9 +18,32 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]")
run_cmake(TestToolsetCudaVersionOnly)
set(RunCMake_GENERATOR_TOOLSET "cuda=0.0")
run_cmake(TestToolsetCudaVersionOnly)
- set(RunCMake_GENERATOR_TOOLSET "cuda=C:\\dummy\\cuda")
+ set(RunCMake_GENERATOR_TOOLSET "cuda=${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset")
run_cmake(TestToolsetCudaPathOnly)
- if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[2456]")
+ set(RunCMake_GENERATOR_TOOLSET "cuda=${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset")
+ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset/CUDAVisualStudioIntegration")
+ run_cmake(TestToolsetCudaPathOnlyOldLayout)
+ file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset")
+ if (VsNormal_Platform MATCHES "^(x64|Win32)$" AND
+ EXISTS "${CMAKE_ROOT}/Templates/MSBuild/FlagTables/${VsNormal_Toolset}_CL.json")
+ set(flagTableDir "${RunCMake_BINARY_DIR}/FlagTables")
+ file(READ "${CMAKE_ROOT}/Templates/MSBuild/FlagTables/${VsNormal_Toolset}_CL.json" flagTableContent)
+ string(REPLACE [["WX-"]] [["TESTWX-"]] flagTableContent "${flagTableContent}")
+ file(REMOVE_RECURSE "${flagTableDir}")
+ file(WRITE "${flagTableDir}/${VsNormal_Platform}_${VsNormal_Toolset}_CL.json" "${flagTableContent}")
+ set(RunCMake_GENERATOR_TOOLSET "${VsNormal_Toolset},customFlagTableDir=${flagTableDir}")
+ set(RunCMake_TEST_VARIANT_DESCRIPTION ":${VsNormal_Platform}_${VsNormal_Toolset}_CL.json")
+ run_cmake(TestToolsetCustomFlagTableDir)
+ file(REMOVE_RECURSE "${flagTableDir}")
+ file(WRITE "${flagTableDir}/${VsNormal_Platform}_CL.json" "${flagTableContent}")
+ set(RunCMake_GENERATOR_TOOLSET "${VsNormal_Toolset},customFlagTableDir=${flagTableDir}")
+ set(RunCMake_TEST_VARIANT_DESCRIPTION ":${VsNormal_Platform}_CL.json")
+ run_cmake(TestToolsetCustomFlagTableDir)
+ unset(RunCMake_TEST_VARIANT_DESCRIPTION)
+ set(RunCMake_GENERATOR_TOOLSET "${VsNormal_Toolset},customFlagTableDir=does_not_exist")
+ run_cmake(BadToolsetCustomFlagTableDir)
+ endif()
+ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[24567]")
set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64")
run_cmake(TestToolsetHostArchBoth)
set(RunCMake_GENERATOR_TOOLSET ",host=x64")
@@ -29,7 +58,7 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]")
run_cmake(BadToolsetHostArch)
set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x86")
run_cmake(BadToolsetHostArchTwice)
- if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[56]")
+ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[567]")
set(RunCMake_GENERATOR_TOOLSET "VCTargetsPath=Test Path")
run_cmake(TestToolsetVCTargetsPathOnly)
set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version")
@@ -76,11 +105,11 @@ endif()
set(RunCMake_GENERATOR_TOOLSET "")
-set(RunCMake_TEST_OPTIONS -T "Extra Toolset")
+set(RunCMake_TEST_OPTIONS -T "Test Toolset" -T "Extra Toolset")
run_cmake(TwoToolsets)
unset(RunCMake_TEST_OPTIONS)
-if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]|Xcode")
+if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[0124567]|Xcode")
set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestToolset-toolchain.cmake)
run_cmake(TestToolsetToolchain)
unset(RunCMake_TEST_OPTIONS)
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnly-stderr.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnly-stderr.txt
index b17745f9a..52367879b 100644
--- a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnly-stderr.txt
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnly-stderr.txt
@@ -5,8 +5,8 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\):
given toolset
- cuda=C:\\dummy\\cuda\\
+ cuda=.*/Tests/RunCMake/CudaStandaloneToolset\\
cannot detect Visual Studio integration files in path
- C:/dummy/cuda/CUDAVisualStudioIntegration/extras/visual_studio_integration/MSBuildExtensions
+ .*/Tests/RunCMake/CudaStandaloneToolset/extras/visual_studio_integration/MSBuildExtensions
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-result.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-stderr.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-stderr.txt
new file mode 100644
index 000000000..3ce79f830
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-stderr.txt
@@ -0,0 +1,12 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+ Generator
+
+ Visual Studio .*
+
+ given toolset
+
+ cuda=.*/Tests/RunCMake/CudaStandaloneToolset\\
+
+ cannot detect Visual Studio integration files in path
+
+ .*/Tests/RunCMake/CudaStandaloneToolset/CUDAVisualStudioIntegration/extras/visual_studio_integration/MSBuildExtensions
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout.cmake
new file mode 100644
index 000000000..2fc38e5c5
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake
new file mode 100644
index 000000000..79752b1f2
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake
@@ -0,0 +1,24 @@
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/main.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file\n ${vcProjectFile}\ndoes not exist.")
+ return()
+endif()
+
+set(TreatWarningAsError_FOUND FALSE)
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+ if(line MATCHES "^ *<TreatWarningAsError>([^<>]*)</TreatWarningAsError>$")
+ set(TreatWarningAsError_FOUND TRUE)
+ set(expectedValue "false")
+ set(actualValue "${CMAKE_MATCH_1}")
+ if(NOT (${actualValue} STREQUAL ${expectedValue}))
+ set(RunCMake_TEST_FAILED "TreatWarningAsError \"${actualValue}\" differs from expected value \"${expectedValue}\".")
+ return()
+ endif()
+ endif()
+endforeach()
+
+if(NOT TreatWarningAsError_FOUND)
+ set(RunCMake_TEST_FAILED "Property TreatWarningAsError not found in project file:\n ${vcProjectFile}.")
+ return()
+endif()
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir.cmake
new file mode 100644
index 000000000..91c6b4437
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+string(APPEND CMAKE_C_FLAGS " -TESTWX-")
+add_executable(main main.c)
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake
index 085bb6b17..854f3dc4d 100644
--- a/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake
@@ -1,7 +1,7 @@
message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE='${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}'")
-if(CMAKE_GENERATOR MATCHES "Visual Studio 1[6]")
+if(CMAKE_GENERATOR MATCHES "Visual Studio 1[67]")
cmake_host_system_information(RESULT is_64_bit QUERY IS_64BIT)
if(is_64_bit)
if(NOT "${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}" STREQUAL "x64")
diff --git a/Tests/RunCMake/GeneratorToolset/VsNormal-stdout.txt b/Tests/RunCMake/GeneratorToolset/VsNormal-stdout.txt
new file mode 100644
index 000000000..25fa3bfbf
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/VsNormal-stdout.txt
@@ -0,0 +1,2 @@
+-- CMAKE_VS_PLATFORM_NAME='[^']+'
+-- CMAKE_VS_PLATFORM_TOOLSET='v[0-9]+'
diff --git a/Tests/RunCMake/GeneratorToolset/VsNormal.cmake b/Tests/RunCMake/GeneratorToolset/VsNormal.cmake
new file mode 100644
index 000000000..e891708d7
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/VsNormal.cmake
@@ -0,0 +1,6 @@
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/defaults.cmake" "# VS Defaults
+set(VsNormal_Platform [[${CMAKE_VS_PLATFORM_NAME}]])
+set(VsNormal_Toolset [[${CMAKE_VS_PLATFORM_TOOLSET}]])
+")
+message(STATUS "CMAKE_VS_PLATFORM_NAME='${CMAKE_VS_PLATFORM_NAME}'")
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
diff --git a/Tests/RunCMake/GeneratorToolset/main.c b/Tests/RunCMake/GeneratorToolset/main.c
new file mode 100644
index 000000000..8488f4e58
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/main.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt
index d9de3f8e5..904ed1177 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt
@@ -8,11 +8,13 @@ Debug/discovery_timeout_test_NOT_BUILT
Debug/discovery_timeout_test_NOT_BUILT(\.exe)?
Debug/discovery_timeout_test_NOT_BUILT
Debug/discovery_timeout_test_NOT_BUILT(\.exe)?
-[^\n]+discovery_timeout_test_NOT_BUILT +\.+\*\*\*Not Run +[0-9.]+ sec
+[^
+]+discovery_timeout_test_NOT_BUILT +\.+\*\*\*Not Run +[0-9.]+ sec
+
0% tests passed, 1 tests failed out of 1
+
Total Test time \(real\) = +[0-9.]+ sec
+
The following tests FAILED:
-[^\n]+discovery_timeout_test_NOT_BUILT \(Not Run\)
+[^
+]+discovery_timeout_test_NOT_BUILT \(Not Run\)
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout1-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout1-stdout.txt
index 0dda49d7c..5febfbfb0 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout1-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout1-stdout.txt
@@ -1,10 +1,12 @@
Test project .*GoogleTest-build
[ \t]*Start [0-9]+: property_timeout.case_no_discovery
-[^\n]+property_timeout.case_no_discovery +\.+\*\*\*Timeout +[0-9.]+ sec
+[^
+]+property_timeout.case_no_discovery +\.+\*\*\*Timeout +[0-9.]+ sec
+
0% tests passed, 1 tests failed out of 1
+
Total Test time \(real\) = +[0-9.]+ sec
+
The following tests FAILED:
-[^\n]*property_timeout.case_no_discovery \(Timeout\)
+[^
+]*property_timeout.case_no_discovery \(Timeout\)
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout2-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout2-stdout.txt
index 72cea558e..c9c719840 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout2-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout2-stdout.txt
@@ -1,10 +1,12 @@
Test project .*GoogleTest-build
[ \t]*Start [0-9]+: property_timeout.case_with_discovery
-[^\n]+property_timeout.case_with_discovery +\.+\*\*\*Timeout +[0-9.]+ sec
+[^
+]+property_timeout.case_with_discovery +\.+\*\*\*Timeout +[0-9.]+ sec
+
0% tests passed, 1 tests failed out of 1
+
Total Test time \(real\) = +[0-9.]+ sec
+
The following tests FAILED:
-[^\n]*property_timeout.case_with_discovery \(Timeout\)
+[^
+]*property_timeout.case_with_discovery \(Timeout\)
diff --git a/Tests/RunCMake/GoogleTest/xml_output.cpp b/Tests/RunCMake/GoogleTest/xml_output.cpp
index 82f0d0237..743a472dc 100644
--- a/Tests/RunCMake/GoogleTest/xml_output.cpp
+++ b/Tests/RunCMake/GoogleTest/xml_output.cpp
@@ -5,7 +5,7 @@
int main(int argc, char** argv)
{
// Note: GoogleTestXML.cmake doesn't actually depend on Google Test as such;
- // it only mimicks the output file creation using the path passed to this
+ // it only mimics the output file creation using the path passed to this
// test without any content
for (int i = 0; i < argc; i++) {
std::string param(argv[i]);
diff --git a/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake b/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake
index 066c83e63..c84e95e00 100644
--- a/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake
+++ b/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake
@@ -18,6 +18,9 @@ run_cmake(BinaryDirectoryInInterface)
set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/DirInInstallPrefix/prefix")
run_cmake(DirInInstallPrefix)
+set(RunCMake_TEST_OPTIONS "--install-prefix=${RunCMake_BINARY_DIR}/DirInInstallPrefix/prefix")
+run_cmake(DirInInstallPrefix)
+
configure_file(
"${RunCMake_SOURCE_DIR}/CMakeLists.txt"
"${RunCMake_BINARY_DIR}/copy/CMakeLists.txt"
@@ -34,14 +37,13 @@ configure_file(
COPYONLY
)
set(RunCMake_TEST_OPTIONS
- "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/copy/SourceDirectoryInInterface/prefix"
+ "--install-prefix=${RunCMake_BINARY_DIR}/copy/SourceDirectoryInInterface/prefix"
"-DTEST_FILE=${RunCMake_BINARY_DIR}/copy/SourceDirectoryInInterface.cmake"
)
set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/copy")
run_cmake(InstallInSrcDir)
unset(RunCMake_TEST_SOURCE_DIR)
-set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/InstallInBinDir-build/prefix")
set(RunCMake_TEST_OPTIONS
"-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/InstallInBinDir-build/prefix"
"-DTEST_FILE=${RunCMake_SOURCE_DIR}/BinaryDirectoryInInterface.cmake"
@@ -77,7 +79,7 @@ foreach(policyStatus NEW OLD "")
set(policySuffix -CMP0052-${policyStatus})
endif()
set(RunCMake_TEST_OPTIONS
- "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/prefix" ${policyOption}
+ "--install-prefix ${RunCMake_BINARY_DIR}/prefix" ${policyOption}
"-DTEST_FILE=${RunCMake_SOURCE_DIR}/BinaryDirectoryInInterface.cmake"
)
# Set the RunCMake_TEST_SOURCE_DIR here to the copy too. This is needed to run
diff --git a/Tests/RunCMake/LinkerLauncher/C-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/C-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/C-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/C-common.cmake b/Tests/RunCMake/LinkerLauncher/C-common.cmake
new file mode 100644
index 000000000..96b004bda
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/C-common.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.c)
diff --git a/Tests/RunCMake/LinkerLauncher/C-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/C-env-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/C-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/C-env.cmake b/Tests/RunCMake/LinkerLauncher/C-env.cmake
new file mode 100644
index 000000000..09b5167b0
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/C-env.cmake
@@ -0,0 +1 @@
+include(C-common.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/C-launch-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/C-launch-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/C-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/C-launch-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/C-launch-env-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/C-launch-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/C-launch-env.cmake b/Tests/RunCMake/LinkerLauncher/C-launch-env.cmake
new file mode 100644
index 000000000..68abcb53b
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/C-launch-env.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(C-env.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/C-launch.cmake b/Tests/RunCMake/LinkerLauncher/C-launch.cmake
new file mode 100644
index 000000000..e66ca203e
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/C-launch.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(C.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/C.cmake b/Tests/RunCMake/LinkerLauncher/C.cmake
new file mode 100644
index 000000000..b55ca8e57
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/C.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_C_LINKER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
+include(C-common.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/CMakeLists.txt b/Tests/RunCMake/LinkerLauncher/CMakeLists.txt
new file mode 100644
index 000000000..7cabeb68b
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.20)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/CXX-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/CXX-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CXX-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/CXX-common.cmake b/Tests/RunCMake/LinkerLauncher/CXX-common.cmake
new file mode 100644
index 000000000..3d2ee0012
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CXX-common.cmake
@@ -0,0 +1,3 @@
+enable_language(CXX)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.cxx)
diff --git a/Tests/RunCMake/LinkerLauncher/CXX-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/CXX-env-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CXX-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/CXX-env.cmake b/Tests/RunCMake/LinkerLauncher/CXX-env.cmake
new file mode 100644
index 000000000..db36956a7
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CXX-env.cmake
@@ -0,0 +1 @@
+include(CXX-common.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/CXX-launch-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/CXX-launch-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CXX-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/CXX-launch-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/CXX-launch-env-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CXX-launch-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/CXX-launch-env.cmake b/Tests/RunCMake/LinkerLauncher/CXX-launch-env.cmake
new file mode 100644
index 000000000..a65cc8985
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CXX-launch-env.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(CXX-env.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/CXX-launch.cmake b/Tests/RunCMake/LinkerLauncher/CXX-launch.cmake
new file mode 100644
index 000000000..3002c9d68
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CXX-launch.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(CXX.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/CXX.cmake b/Tests/RunCMake/LinkerLauncher/CXX.cmake
new file mode 100644
index 000000000..4326614ac
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/CXX.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_CXX_LINKER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
+include(CXX-common.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJC-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJC-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-common.cmake b/Tests/RunCMake/LinkerLauncher/OBJC-common.cmake
new file mode 100644
index 000000000..7b565f4ca
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJC-common.cmake
@@ -0,0 +1,3 @@
+enable_language(OBJC)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.m)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJC-env-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJC-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-env.cmake b/Tests/RunCMake/LinkerLauncher/OBJC-env.cmake
new file mode 100644
index 000000000..949e88d31
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJC-env.cmake
@@ -0,0 +1 @@
+include(OBJC-common.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-launch-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJC-launch-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJC-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-launch-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJC-launch-env-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJC-launch-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-launch-env.cmake b/Tests/RunCMake/LinkerLauncher/OBJC-launch-env.cmake
new file mode 100644
index 000000000..1cf13d3df
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJC-launch-env.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(OBJC-env.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-launch.cmake b/Tests/RunCMake/LinkerLauncher/OBJC-launch.cmake
new file mode 100644
index 000000000..43e852164
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJC-launch.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(OBJC.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJC.cmake b/Tests/RunCMake/LinkerLauncher/OBJC.cmake
new file mode 100644
index 000000000..e0360b386
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJC.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_OBJC_LINKER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
+include(OBJC-common.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJCXX-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-common.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX-common.cmake
new file mode 100644
index 000000000..e2ee4eb2d
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-common.cmake
@@ -0,0 +1,3 @@
+enable_language(OBJCXX)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.mm)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJCXX-env-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-env.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX-env.cmake
new file mode 100644
index 000000000..3ed966d19
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-env.cmake
@@ -0,0 +1 @@
+include(OBJCXX-common.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env-Build-stdout.txt
new file mode 100644
index 000000000..3313e31f6
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env.cmake
new file mode 100644
index 000000000..04c916a18
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(OBJCXX-env.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-launch.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch.cmake
new file mode 100644
index 000000000..5a54bffeb
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(OBJCXX.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX.cmake
new file mode 100644
index 000000000..366774537
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/OBJCXX.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_OBJCXX_LINKER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
+include(OBJCXX-common.cmake)
diff --git a/Tests/RunCMake/LinkerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/LinkerLauncher/RunCMakeTest.cmake
new file mode 100644
index 000000000..8f2bf63f4
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/RunCMakeTest.cmake
@@ -0,0 +1,37 @@
+include(RunCMake)
+
+function(run_linker_launcher lang)
+ # Preserve build tree so we can reuse it for the ${lang}-Build subtest below
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${lang}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(${lang})
+
+ set(RunCMake_TEST_OUTPUT_MERGE 1)
+ if("${RunCMake_GENERATOR}" MATCHES "Ninja")
+ set(verbose_args -- -v)
+ endif()
+ run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build . ${verbose_args})
+endfunction()
+
+function(run_linker_launcher_env lang)
+ string(REGEX REPLACE "-.*" "" core_lang "${lang}")
+ set(ENV{CMAKE_${core_lang}_LINKER_LAUNCHER} "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
+ run_linker_launcher(${lang})
+ unset(ENV{CMAKE_${core_lang}_LINKER_LAUNCHER})
+endfunction()
+
+set(langs C CXX)
+if(CMake_TEST_OBJC)
+ list(APPEND langs OBJC OBJCXX)
+endif()
+
+foreach(lang ${langs})
+ run_linker_launcher(${lang})
+ run_linker_launcher_env(${lang}-env)
+ if(NOT RunCMake_GENERATOR STREQUAL "Watcom WMake")
+ run_linker_launcher(${lang}-launch)
+ run_linker_launcher_env(${lang}-launch-env)
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/LinkerLauncher/main.c b/Tests/RunCMake/LinkerLauncher/main.c
new file mode 100644
index 000000000..8488f4e58
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/main.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/LinkerLauncher/main.cxx b/Tests/RunCMake/LinkerLauncher/main.cxx
new file mode 100644
index 000000000..f8b643afb
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/main.cxx
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/LinkerLauncher/main.m b/Tests/RunCMake/LinkerLauncher/main.m
new file mode 100644
index 000000000..8488f4e58
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/main.m
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/LinkerLauncher/main.mm b/Tests/RunCMake/LinkerLauncher/main.mm
new file mode 100644
index 000000000..f8b643afb
--- /dev/null
+++ b/Tests/RunCMake/LinkerLauncher/main.mm
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake b/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake
index 189de6417..51f4f52cc 100644
--- a/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake
+++ b/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake
@@ -1,5 +1,10 @@
set(log "${RunCMake_BINARY_DIR}/CustomCommandDepfile-build/build.ninja")
file(READ "${log}" build_file)
+
+set(RunCMake_TEST_FAILED)
if(NOT "${build_file}" MATCHES "depfile = test\\.d")
- set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
+ list(APPEND RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
+endif()
+if(NOT "${build_file}" MATCHES "depfile = test_Debug\\.d")
+ list(APPEND RunCMake_TEST_FAILED "\nLog file:\n ${log}\ndoes not have expected line: depfile = test_Debug.d")
endif()
diff --git a/Tests/RunCMake/Ninja/CustomCommandDepfile.cmake b/Tests/RunCMake/Ninja/CustomCommandDepfile.cmake
index dbef2a535..0838d1433 100644
--- a/Tests/RunCMake/Ninja/CustomCommandDepfile.cmake
+++ b/Tests/RunCMake/Ninja/CustomCommandDepfile.cmake
@@ -6,6 +6,17 @@ add_custom_command(
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPFILE "test.d"
)
-add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/hello.copy.c")
+
+add_custom_command(
+ OUTPUT hello.copy2.c
+ COMMAND "${CMAKE_COMMAND}" -E copy
+ "${CMAKE_CURRENT_SOURCE_DIR}/hello.c"
+ hello.copy2.c
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ DEPFILE "test_$<CONFIG>.d"
+ )
+
+add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/hello.copy.c"
+ "${CMAKE_CURRENT_BINARY_DIR}/hello.copy2.c")
include(CheckNoPrefixSubDir.cmake)
diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
index 0c0619dbf..3f239b974 100644
--- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
@@ -18,6 +18,9 @@ else()
message(FATAL_ERROR "'ninja --version' reported:\n${ninja_out}")
endif()
+# Sanitize NINJA_STATUS since we expect default behavior.
+unset(ENV{NINJA_STATUS})
+
if(CMAKE_HOST_WIN32)
run_cmake(SelectCompilerWindows)
else()
@@ -67,7 +70,7 @@ run_CMP0058(WARN-by)
run_CMP0058(NEW-no)
run_CMP0058(NEW-by)
-run_cmake(CustomCommandDepfile)
+run_cmake_with_options(CustomCommandDepfile -DCMAKE_BUILD_TYPE=Debug)
run_cmake(CustomCommandJobPool)
run_cmake(JobPoolUsesTerminal)
@@ -163,12 +166,12 @@ run_LooseObjectDepends()
function (run_AssumedSources)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AssumedSources-build)
run_cmake(AssumedSources)
- run_ninja("${RunCMake_TEST_BINARY_DIR}" "target.c")
+ run_ninja("${RunCMake_TEST_BINARY_DIR}" "${RunCMake_TEST_BINARY_DIR}/target.c")
if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/target.c")
message(FATAL_ERROR
"Dependencies for an assumed source did not hook up properly for 'target.c'.")
endif ()
- run_ninja("${RunCMake_TEST_BINARY_DIR}" "target-no-depends.c")
+ run_ninja("${RunCMake_TEST_BINARY_DIR}" "${RunCMake_TEST_BINARY_DIR}/target-no-depends.c")
if (EXISTS "${RunCMake_TEST_BINARY_DIR}/target-no-depends.c")
message(FATAL_ERROR
"Dependencies for an assumed source were magically hooked up for 'target-no-depends.c'.")
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake
index c595b1097..a7837ca98 100644
--- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake
@@ -1,5 +1,10 @@
set(log "${RunCMake_BINARY_DIR}/CustomCommandDepfile-build/CMakeFiles/impl-Debug.ninja")
file(READ "${log}" build_file)
+
+set(RunCMake_TEST_FAILED)
if(NOT "${build_file}" MATCHES "depfile = test\\.d")
- set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
+ list(APPEND RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
+endif()
+if(NOT "${build_file}" MATCHES "depfile = test_Debug\\.d")
+ list(APPEND RunCMake_TEST_FAILED "\nLog file:\n ${log}\ndoes not have expected line: depfile = test_Debug.d")
endif()
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile.cmake
index 1a42670c9..4f8c11430 100644
--- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile.cmake
@@ -6,4 +6,15 @@ add_custom_command(
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPFILE "test.d"
)
-add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/main.copy.c")
+
+add_custom_command(
+ OUTPUT main.copy2.c
+ COMMAND "${CMAKE_COMMAND}" -E copy
+ "${CMAKE_CURRENT_SOURCE_DIR}/main.c"
+ main.copy2.c
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ DEPFILE "test_$<CONFIG>.d"
+ )
+
+add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/main.copy.c"
+ "${CMAKE_CURRENT_BINARY_DIR}/main.copy2.c")
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index e7acbc284..559c8f796 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -5,6 +5,9 @@ include(RunCMake)
set(RunCMake_GENERATOR "Ninja Multi-Config")
set(RunCMake_GENERATOR_IS_MULTI_CONFIG 1)
+# Sanitize NINJA_STATUS since we expect default behavior.
+unset(ENV{NINJA_STATUS})
+
function(check_files dir)
cmake_parse_arguments(_check_files "" "" "INCLUDE;EXCLUDE" ${ARGN})
diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt
index 4dbd86144..6a7c17167 100644
--- a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt
@@ -3,7 +3,7 @@ CMake Error at BadSourceExpression3.cmake:2 \(add_library\):
\$<TARGET_OBJECTS:NotObjLib>
- Objects of target "NotObjLib" referenced but is not an allowed library
- types \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\).
+ Objects of target "NotObjLib" referenced but is not one of the allowed
+ target types \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\).
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/ParseImplicitData/linux-C-GNU-10.2.1-static-libgcc.input b/Tests/RunCMake/ParseImplicitData/linux-C-GNU-10.2.1-static-libgcc.input
new file mode 100644
index 000000000..0aaf05efd
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitData/linux-C-GNU-10.2.1-static-libgcc.input
@@ -0,0 +1,74 @@
+CMAKE_LANG=C
+CMAKE_LINKER=/usr/bin/ld
+CMAKE_C_COMPILER_ABI=ELF
+CMAKE_C_COMPILER_AR=/usr/bin/gcc-ar-10
+CMAKE_C_COMPILER_ARCHITECTURE_ID=
+CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN=
+CMAKE_C_COMPILER_ID=GNU
+CMAKE_C_COMPILER_LAUNCHER=
+CMAKE_C_COMPILER_LOADED=1
+CMAKE_C_COMPILER_RANLIB=/usr/bin/gcc-ranlib-10
+CMAKE_C_COMPILER_TARGET=
+CMAKE_C_COMPILER_VERSION=10.2.1
+CMAKE_C_COMPILER_VERSION_INTERAL=
+Change Dir: /tmp/ii/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_2fff5/fast && /usr/bin/gmake -f CMakeFiles/cmTC_2fff5.dir/build.make CMakeFiles/cmTC_2fff5.dir/build
+gmake[1]: Entering directory '/tmp/ii/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o
+/usr/bin/gcc -static-libgcc -v -o CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o -c "/tmp/CMake/Modules/CMakeCCompilerABI.c"
+Using built-in specs.
+COLLECT_GCC=/usr/bin/gcc
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-o' 'CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/cc1 -quiet -v -imultiarch x86_64-linux-gnu /tmp/CMake/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -o /tmp/cc1V18pC.s
+GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"
+#include "..." search starts here:
+#include <...> search starts here:
+ /usr/lib/gcc/x86_64-linux-gnu/10/include
+ /usr/local/include
+ /usr/include/x86_64-linux-gnu
+ /usr/include
+End of search list.
+GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+Compiler executable checksum: 1f803793fa2e3418c492b25e7d3eac2f
+COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-o' 'CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+ as -v --64 -o CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o /tmp/cc1V18pC.s
+GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-o' 'CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+Linking C executable cmTC_2fff5
+"/tmp/CMake/bin/cmake" -E cmake_link_script CMakeFiles/cmTC_2fff5.dir/link.txt --verbose=1
+/usr/bin/gcc -static-libgcc -v -rdynamic CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o -o cmTC_2fff5
+Using built-in specs.
+COLLECT_GCC=/usr/bin/gcc
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-rdynamic' '-o' 'cmTC_2fff5' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/cc0iqkvc.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_2fff5 /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o
+COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-rdynamic' '-o' 'cmTC_2fff5' '-mtune=generic' '-march=x86-64'
+gmake[1]: Leaving directory '/tmp/ii/CMakeFiles/CMakeTmp'
diff --git a/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input b/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input
new file mode 100644
index 000000000..387f14901
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input
@@ -0,0 +1,79 @@
+CMAKE_LANG=CXX
+CMAKE_LINKER=/usr/bin/ld
+CMAKE_CXX_COMPILER_ABI=ELF
+CMAKE_CXX_COMPILER_AR=/usr/bin/gcc-ar-10
+CMAKE_CXX_COMPILER_ARCHITECTURE_ID=
+CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN=
+CMAKE_CXX_COMPILER_ID=GNU
+CMAKE_CXX_COMPILER_LAUNCHER=
+CMAKE_CXX_COMPILER_LOADED=1
+CMAKE_CXX_COMPILER_RANLIB=/usr/bin/gcc-ranlib-10
+CMAKE_CXX_COMPILER_TARGET=
+CMAKE_CXX_COMPILER_VERSION=10.2.1
+CMAKE_CXX_COMPILER_VERSION_INTERAL=
+CMAKE_CXX_IMPLICIT_LINK_LIBRARY_stdc++=/usr/lib/gcc/x86_64-linux-gnu/10/libstdc++.a
+Change Dir: /tmp/ii/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_339dd/fast && /usr/bin/gmake -f CMakeFiles/cmTC_339dd.dir/build.make CMakeFiles/cmTC_339dd.dir/build
+gmake[1]: Entering directory '/tmp/ii/CMakeFiles/CMakeTmp'
+Building CXX object CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o
+/usr/bin/g++ -static-libstdc++ -v -o CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o -c "/tmp/CMake/Modules/CMakeCXXCompilerABI.cpp"
+Using built-in specs.
+COLLECT_GCC=/usr/bin/g++
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /tmp/CMake/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -o /tmp/ccjKk4SK.s
+GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/10"
+ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"
+#include "..." search starts here:
+#include <...> search starts here:
+ /usr/include/c++/10
+ /usr/include/x86_64-linux-gnu/c++/10
+ /usr/include/c++/10/backward
+ /usr/lib/gcc/x86_64-linux-gnu/10/include
+ /usr/local/include
+ /usr/include/x86_64-linux-gnu
+ /usr/include
+End of search list.
+GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+Compiler executable checksum: 048fcaee3460a99eb0d68522358720e1
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ as -v --64 -o CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccjKk4SK.s
+GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+Linking CXX executable cmTC_339dd
+"/tmp/CMake/bin/cmake" -E cmake_link_script CMakeFiles/cmTC_339dd.dir/link.txt --verbose=1
+/usr/bin/g++ -static-libstdc++ -v -rdynamic CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_339dd
+Using built-in specs.
+COLLECT_GCC=/usr/bin/g++
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_339dd' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/cc0slq0h.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_339dd /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o -Bstatic -lstdc++ -Bdynamic -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_339dd' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+gmake[1]: Leaving directory '/tmp/ii/CMakeFiles/CMakeTmp'
diff --git a/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input b/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input
new file mode 100644
index 000000000..16b38d2d0
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input
@@ -0,0 +1,79 @@
+CMAKE_LANG=Fortran
+CMAKE_LINKER=/usr/bin/ld
+CMAKE_Fortran_COMPILER_ABI=
+CMAKE_Fortran_COMPILER_AR=/usr/bin/gcc-ar-10
+CMAKE_Fortran_COMPILER_ARCHITECTURE_ID=
+CMAKE_Fortran_COMPILER_EXTERNAL_TOOLCHAIN=
+CMAKE_Fortran_COMPILER_ID=GNU
+CMAKE_Fortran_COMPILER_LAUNCHER=
+CMAKE_Fortran_COMPILER_LOADED=1
+CMAKE_Fortran_COMPILER_RANLIB=/usr/bin/gcc-ranlib-10
+CMAKE_Fortran_COMPILER_TARGET=
+CMAKE_Fortran_COMPILER_VERSION=10.2.1
+CMAKE_Fortran_COMPILER_VERSION_INTERAL=
+CMAKE_Fortran_IMPLICIT_LINK_LIBRARY_gfortran=/usr/lib/gcc/x86_64-linux-gnu/10/libgfortran.a
+Change Dir: /tmp/ii/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_07a63/fast && /usr/bin/gmake -f CMakeFiles/cmTC_07a63.dir/build.make CMakeFiles/cmTC_07a63.dir/build
+gmake[1]: Entering directory '/tmp/ii/CMakeFiles/CMakeTmp'
+Building Fortran object CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o
+/usr/bin/gfortran -static-libgfortran -v -c "/tmp/CMake/Modules/CMakeFortranCompilerABI.F" -o CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o
+Using built-in specs.
+COLLECT_GCC=/usr/bin/gfortran
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+COLLECT_GCC_OPTIONS='-static-libgfortran' '-v' '-c' '-o' 'CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/f951 /tmp/CMake/Modules/CMakeFortranCompilerABI.F -ffixed-form -cpp=/tmp/ccA5jWwS.f90 -quiet -v -imultiarch x86_64-linux-gnu /tmp/CMake/Modules/CMakeFortranCompilerABI.F -quiet -dumpbase CMakeFortranCompilerABI.F -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o -version -fintrinsic-modules-path /usr/lib/gcc/x86_64-linux-gnu/10/finclude -fpre-include=/usr/include/finclude/x86_64-linux-gnu/math-vector-fortran.h -o /tmp/cclOgAvW.s
+GNU Fortran (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include"
+#include "..." search starts here:
+#include <...> search starts here:
+ /usr/lib/gcc/x86_64-linux-gnu/10/finclude
+ /usr/lib/gcc/x86_64-linux-gnu/10/include
+ /usr/local/include
+ /usr/include/x86_64-linux-gnu
+ /usr/include
+End of search list.
+GNU Fortran2008 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu)
+ compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+COLLECT_GCC_OPTIONS='-static-libgfortran' '-v' '-c' '-o' 'CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o' '-mtune=generic' '-march=x86-64'
+ as -v --64 -o CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o /tmp/cclOgAvW.s
+GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-static-libgfortran' '-v' '-c' '-o' 'CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o' '-mtune=generic' '-march=x86-64'
+Linking Fortran executable cmTC_07a63
+"/tmp/CMake/bin/cmake" -E cmake_link_script CMakeFiles/cmTC_07a63.dir/link.txt --verbose=1
+/usr/bin/gfortran -v -static-libgfortran CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o -o cmTC_07a63
+Driving: /usr/bin/gfortran -v -static-libgfortran CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o -o cmTC_07a63 -Wl,-Bstatic -l gfortran -Wl,-Bdynamic -l m -shared-libgcc
+Using built-in specs.
+COLLECT_GCC=/usr/bin/gfortran
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
+OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
+Thread model: posix
+Supported LTO compression algorithms: zlib zstd
+gcc version 10.2.1 20210110 (Debian 10.2.1-6)
+Reading specs from /usr/lib/gcc/x86_64-linux-gnu/10/libgfortran.spec
+rename spec lib to liborig
+COLLECT_GCC_OPTIONS='-v' '-static-libgfortran' '-o' 'cmTC_07a63' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-static-libgfortran' '-o' 'cmTC_07a63' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/ccbtSp3p.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lquadmath -plugin-opt=-pass-through=-lm -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_07a63 /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o -Bstatic -lgfortran -Bdynamic -lm -lgcc_s -lgcc --as-needed -lquadmath --no-as-needed -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o
+COLLECT_GCC_OPTIONS='-v' '-static-libgfortran' '-o' 'cmTC_07a63' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+gmake[1]: Leaving directory '/tmp/ii/CMakeFiles/CMakeTmp'
diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake b/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake
index 2d3abccb6..e501f122e 100644
--- a/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake
+++ b/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake
@@ -23,6 +23,9 @@ set(targets
hand-C-empty hand-CXX-empty
hand-C-relative hand-CXX-relative
linux-C-GNU-7.3.0 linux-CXX-GNU-7.3.0 linux-Fortran-GNU-7.3.0
+ linux-C-GNU-10.2.1-static-libgcc
+ linux-CXX-GNU-10.2.1-static-libstdc++
+ linux-Fortran-GNU-10.2.1-static-libgfortran
linux-C-Intel-18.0.0.20170811 linux-CXX-Intel-18.0.0.20170811
linux-C-PGI-18.10.1 linux-CXX-PGI-18.10.1
linux-Fortran-PGI-18.10.1 linux_pgf77-Fortran-PGI-18.10.1
diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-C-GNU-10.2.1-static-libgcc.output b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-C-GNU-10.2.1-static-libgcc.output
new file mode 100644
index 000000000..2f89e1524
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-C-GNU-10.2.1-static-libgcc.output
@@ -0,0 +1 @@
+/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include
diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output
new file mode 100644
index 000000000..b97cdc825
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output
@@ -0,0 +1 @@
+/usr/include/c\+\+/10;/usr/include/x86_64-linux-gnu/c\+\+/10;/usr/include/c\+\+/10/backward;/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include
diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output
new file mode 100644
index 000000000..34c33a73b
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output
@@ -0,0 +1 @@
+/usr/lib/gcc/x86_64-linux-gnu/10/finclude;/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
index 1f3468b0e..dcdc7f1b9 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
@@ -23,6 +23,9 @@ set(targets
hand-C-empty hand-CXX-empty
hand-C-relative hand-CXX-relative
linux-C-GNU-7.3.0 linux-CXX-GNU-7.3.0 linux-Fortran-GNU-7.3.0
+ linux-C-GNU-10.2.1-static-libgcc
+ linux-CXX-GNU-10.2.1-static-libstdc++
+ linux-Fortran-GNU-10.2.1-static-libgfortran
linux-C-Intel-18.0.0.20170811 linux-CXX-Intel-18.0.0.20170811
linux-C-PGI-18.10.1 linux-CXX-PGI-18.10.1
linux-Fortran-PGI-18.10.1 linux_pgf77-Fortran-PGI-18.10.1
@@ -67,7 +70,7 @@ function(load_compiler_info infile lang_var outcmvars_var outstr_var)
string(REGEX REPLACE "\r?\n" ";" in_lines "${in}")
foreach(line IN LISTS in_lines)
# check for special CMAKE variable lines and parse them if found
- if("${line}" MATCHES "^CMAKE_([_A-Za-z0-9]+)=(.*)$")
+ if("${line}" MATCHES "^CMAKE_([_A-Za-z0-9+]+)=(.*)$")
if("${CMAKE_MATCH_1}" STREQUAL "LANG") # handle CMAKE_LANG here
set(lang "${CMAKE_MATCH_2}")
else()
@@ -162,12 +165,12 @@ foreach(t ${targets})
if("${state}" STREQUAL "done")
message("empty parse failed: ${idirs}, log=${log}")
endif()
- elseif(NOT "${idirs}" STREQUAL "${idirs_output}")
- message("${t} parse failed: state=${state}, '${idirs}' does not match '${idirs_output}'")
- elseif(NOT "${implicit_libs}" STREQUAL "${implicit_lib_output}")
- message("${t} parse failed: state=${state}, '${implicit_libs}' does not match '${implicit_lib_output}'")
- elseif((library_arch OR library_arch_output) AND NOT "${library_arch}" STREQUAL "${library_arch_output}")
- message("${t} parse failed: state=${state}, '${library_arch}' does not match '${library_arch_output}'")
+ elseif(NOT "${idirs}" MATCHES "^${idirs_output}$")
+ message("${t} parse failed: state=${state}, '${idirs}' does not match '^${idirs_output}$'")
+ elseif(NOT "${implicit_libs}" MATCHES "^${implicit_lib_output}$")
+ message("${t} parse failed: state=${state}, '${implicit_libs}' does not match '^${implicit_lib_output}$'")
+ elseif((library_arch OR library_arch_output) AND NOT "${library_arch}" MATCHES "^${library_arch_output}$")
+ message("${t} parse failed: state=${state}, '${library_arch}' does not match '^${library_arch_output}$'")
endif()
unload_compiler_info("${cmvars}")
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/aix-CXX-XLClang-16.1.0.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/aix-CXX-XLClang-16.1.0.1.output
index 2dc5832b3..3a57464f0 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/aix-CXX-XLClang-16.1.0.1.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/aix-CXX-XLClang-16.1.0.1.output
@@ -1,2 +1,2 @@
-libs=xlopt;xlipa;xl;c++;Ccore;pthreads;m;c
+libs=xlopt;xlipa;xl;c\+\+;Ccore;pthreads;m;c
dirs=/opt/IBM/xlmass/9.1.0/lib/aix61;/opt/IBM/xlc/16.1.0/lib;/opt/IBM/xlC/16.1.0/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-8.7.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-8.7.output
index 674975cbd..0373d89a6 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-8.7.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-8.7.output
@@ -1,2 +1,2 @@
-libs=AtpSigHandler;AtpSigHCommData;pthread;sci_cray_mpi_mp;m;f;sci_cray_mp;craymp;m;pthread;f;hugetlbfs;mpich_cray;rt;pthread;ugni;pmi;pgas-dmapp;fi;u;rt;dmapp;ugni;udreg;pthread;m;cray-c++-rts;stdc++;xpmem;dmapp;pthread;pmi;pthread;alpslli;pthread;wlm_detect;ugni;pthread;alpsutil;pthread;rca;udreg;quadmath;m;omp;rt;craymp;pthread;rt;dl;cray-c++-rts;stdc++;m;modules;m;rt;fi;m;quadmath;rt;craymath;m;gfortran;quadmath;rt;f;m;pthread;rt;u;rt;dl;cray-c++-rts;stdc++;m;csup;rt;atomic;stdc++;pthread;c;csup;m;gcc
+libs=AtpSigHandler;AtpSigHCommData;pthread;sci_cray_mpi_mp;m;f;sci_cray_mp;craymp;m;pthread;f;hugetlbfs;mpich_cray;rt;pthread;ugni;pmi;pgas-dmapp;fi;u;rt;dmapp;ugni;udreg;pthread;m;cray-c\+\+-rts;stdc\+\+;xpmem;dmapp;pthread;pmi;pthread;alpslli;pthread;wlm_detect;ugni;pthread;alpsutil;pthread;rca;udreg;quadmath;m;omp;rt;craymp;pthread;rt;dl;cray-c\+\+-rts;stdc\+\+;m;modules;m;rt;fi;m;quadmath;rt;craymath;m;gfortran;quadmath;rt;f;m;pthread;rt;u;rt;dl;cray-c\+\+-rts;stdc\+\+;m;csup;rt;atomic;stdc\+\+;pthread;c;csup;m;gcc
dirs=/opt/gcc/6.1.0/snos/lib64;/opt/cray/pe/libsci/18.07.1/CRAY/8.6/x86_64/lib;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.3/gni/mpich-cray/8.6/lib;/opt/cray/rca/2.2.16-6.0.5.0_15.34__g5e09e6d.ari/lib64;/opt/cray/alps/6.5.28-6.0.5.0_18.6__g13a91b6.ari/lib64;/opt/cray/xpmem/2.2.4-6.0.5.1_8.26__g35d5e73.ari/lib64;/opt/cray/dmapp/7.1.1-6.0.5.0_49.8__g1125556.ari/lib64;/opt/cray/pe/pmi/5.0.14/lib64;/opt/cray/ugni/6.0.14-6.0.5.0_16.9__g19583bb.ari/lib64;/opt/cray/udreg/2.3.2-6.0.5.0_13.12__ga14955a.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/8.7.4/cce/x86_64/lib;/opt/cray/wlm_detect/1.3.2-6.0.5.0_3.1__g388ccd5.ari/lib64;/usr/lib64;/lib64;/opt/gcc/6.1.0/snos/lib/gcc/x86_64-suse-linux/6.1.0;/opt/cray/pe/cce/8.7.4/binutils/x86_64/x86_64-unknown-linux-gnu/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-9.0-hlist-ad.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-9.0-hlist-ad.output
index 1bf2f6d05..0f52e8b34 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-9.0-hlist-ad.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-9.0-hlist-ad.output
@@ -1,2 +1,2 @@
-libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;atomic;tcmalloc_minimal;cray-c++-rts;stdc++;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc
+libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;atomic;tcmalloc_minimal;cray-c\+\+-rts;stdc\+\+;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc
dirs=/opt/gcc/8.1.0/snos/lib64;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.8/gni/mpich-cray/9.0/lib;/opt/cray/pe/libsci/19.06.1/CRAY/9.0/x86_64/lib;/opt/cray/rca/2.2.18-6.0.7.0_33.3__g2aa4f39.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/9.0.0/cce/x86_64/lib;/usr/lib64;/lib64;/opt/cray/pe/cce/9.0.0/cce-clang/x86_64/lib/clang/9.0.0/lib/linux;/opt/gcc/8.1.0/snos/lib/gcc/x86_64-suse-linux/8.1.0;/opt/cray/pe/cce/9.0.0/binutils/x86_64/x86_64-unknown-linux-gnu/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Intel-18.0.2.20180210.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Intel-18.0.2.20180210.output
index e9e67396f..5b8ae8df0 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Intel-18.0.2.20180210.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Intel-18.0.2.20180210.output
@@ -1,2 +1,2 @@
-libs=imf;svml;irng;m;ipgo;decimal;cilkrts;stdc++;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c
+libs=imf;svml;irng;m;ipgo;decimal;cilkrts;stdc\+\+;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c
dirs=/opt/intel/2018.2.199/compilers_and_libraries_2018/linux/mkl/lib/intel64;/opt/intel/2018.2.199/compilers_and_libraries_2018.2.199/linux/compiler/lib/intel64_lin;/opt/gcc/6.3.0/snos/lib/gcc/x86_64-suse-linux/6.3.0;/opt/gcc/6.3.0/snos/lib64;/lib64;/usr/lib64;/opt/gcc/6.3.0/snos/lib;/lib;/usr/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-8.7.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-8.7.output
index 7daa29d40..00281d5c2 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-8.7.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-8.7.output
@@ -1,2 +1,2 @@
-libs=AtpSigHandler;AtpSigHCommData;pthread;sci_cray_mpi_mp;m;f;sci_cray_mp;craymp;m;pthread;f;hugetlbfs;mpichcxx_cray;rt;pthread;ugni;pmi;mpich_cray;rt;pthread;ugni;pmi;pgas-dmapp;fi;u;rt;dmapp;ugni;udreg;pthread;m;cray-c++-rts;stdc++;xpmem;dmapp;pthread;pmi;pthread;alpslli;pthread;wlm_detect;ugni;pthread;alpsutil;pthread;rca;udreg;quadmath;m;omp;rt;craymp;pthread;rt;dl;cray-c++-rts;stdc++;m;modules;m;rt;fi;m;quadmath;rt;craymath;m;gfortran;quadmath;rt;f;m;pthread;rt;u;rt;dl;cray-c++-rts;stdc++;m;csup;rt;atomic;cray-c++-rts;stdc++;supc++;stdc++;pthread;c;csup;m;gcc
+libs=AtpSigHandler;AtpSigHCommData;pthread;sci_cray_mpi_mp;m;f;sci_cray_mp;craymp;m;pthread;f;hugetlbfs;mpichcxx_cray;rt;pthread;ugni;pmi;mpich_cray;rt;pthread;ugni;pmi;pgas-dmapp;fi;u;rt;dmapp;ugni;udreg;pthread;m;cray-c\+\+-rts;stdc\+\+;xpmem;dmapp;pthread;pmi;pthread;alpslli;pthread;wlm_detect;ugni;pthread;alpsutil;pthread;rca;udreg;quadmath;m;omp;rt;craymp;pthread;rt;dl;cray-c\+\+-rts;stdc\+\+;m;modules;m;rt;fi;m;quadmath;rt;craymath;m;gfortran;quadmath;rt;f;m;pthread;rt;u;rt;dl;cray-c\+\+-rts;stdc\+\+;m;csup;rt;atomic;cray-c\+\+-rts;stdc\+\+;supc\+\+;stdc\+\+;pthread;c;csup;m;gcc
dirs=/opt/gcc/6.1.0/snos/lib64;/opt/cray/pe/libsci/18.07.1/CRAY/8.6/x86_64/lib;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.3/gni/mpich-cray/8.6/lib;/opt/cray/rca/2.2.16-6.0.5.0_15.34__g5e09e6d.ari/lib64;/opt/cray/alps/6.5.28-6.0.5.0_18.6__g13a91b6.ari/lib64;/opt/cray/xpmem/2.2.4-6.0.5.1_8.26__g35d5e73.ari/lib64;/opt/cray/dmapp/7.1.1-6.0.5.0_49.8__g1125556.ari/lib64;/opt/cray/pe/pmi/5.0.14/lib64;/opt/cray/ugni/6.0.14-6.0.5.0_16.9__g19583bb.ari/lib64;/opt/cray/udreg/2.3.2-6.0.5.0_13.12__ga14955a.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/8.7.4/cce/x86_64/lib;/opt/cray/wlm_detect/1.3.2-6.0.5.0_3.1__g388ccd5.ari/lib64;/usr/lib64;/lib64;/opt/gcc/6.1.0/snos/lib/gcc/x86_64-suse-linux/6.1.0;/opt/cray/pe/cce/8.7.4/binutils/x86_64/x86_64-unknown-linux-gnu/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-9.0-hlist-ad.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-9.0-hlist-ad.output
index 958a6b1cf..a7287d37a 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-9.0-hlist-ad.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-9.0-hlist-ad.output
@@ -1,2 +1,2 @@
-libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;mpichcxx_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;atomic;cray-c++-rts;cray-c++-rts;stdc++;supc++;tcmalloc_minimal;cray-c++-rts;stdc++;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc
+libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;mpichcxx_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;atomic;cray-c\+\+-rts;cray-c\+\+-rts;stdc\+\+;supc\+\+;tcmalloc_minimal;cray-c\+\+-rts;stdc\+\+;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc
dirs=/opt/gcc/8.1.0/snos/lib64;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.8/gni/mpich-cray/9.0/lib;/opt/cray/pe/libsci/19.06.1/CRAY/9.0/x86_64/lib;/opt/cray/rca/2.2.18-6.0.7.0_33.3__g2aa4f39.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/9.0.0/cce/x86_64/lib;/usr/lib64;/lib64;/opt/cray/pe/cce/9.0.0/cce-clang/x86_64/lib/clang/9.0.0/lib/linux;/opt/gcc/8.1.0/snos/lib/gcc/x86_64-suse-linux/8.1.0;/opt/cray/pe/cce/9.0.0/binutils/x86_64/x86_64-unknown-linux-gnu/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-GNU-7.3.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-GNU-7.3.0.output
index 40d0047c7..ead480425 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-GNU-7.3.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-GNU-7.3.0.output
@@ -1,2 +1,2 @@
-libs=AtpSigHandler;AtpSigHCommData;pthread;sci_gnu_71_mpi;sci_gnu_71;pthread;hugetlbfs;mpichcxx_gnu_71;rt;ugni;pthread;pmi;mpich_gnu_71;rt;ugni;pthread;pmi;pthread;alpslli;pthread;wlm_detect;alpsutil;pthread;rca;ugni;pthread;xpmem;udreg;gfortran;quadmath;mvec;m;pthread;stdc++;m;gcc;c
+libs=AtpSigHandler;AtpSigHCommData;pthread;sci_gnu_71_mpi;sci_gnu_71;pthread;hugetlbfs;mpichcxx_gnu_71;rt;ugni;pthread;pmi;mpich_gnu_71;rt;ugni;pthread;pmi;pthread;alpslli;pthread;wlm_detect;alpsutil;pthread;rca;ugni;pthread;xpmem;udreg;gfortran;quadmath;mvec;m;pthread;stdc\+\+;m;gcc;c
dirs=/opt/cray/pe/libsci/18.07.1/GNU/7.1/x86_64/lib;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.3/gni/mpich-gnu/7.1/lib;/opt/cray/rca/2.2.16-6.0.5.0_15.34__g5e09e6d.ari/lib64;/opt/cray/alps/6.5.28-6.0.5.0_18.6__g13a91b6.ari/lib64;/opt/cray/xpmem/2.2.4-6.0.5.1_8.26__g35d5e73.ari/lib64;/opt/cray/pe/pmi/5.0.14/lib64;/opt/cray/ugni/6.0.14-6.0.5.0_16.9__g19583bb.ari/lib64;/opt/cray/udreg/2.3.2-6.0.5.0_13.12__ga14955a.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/wlm_detect/1.3.2-6.0.5.0_3.1__g388ccd5.ari/lib64;/opt/gcc/7.3.0/snos/lib/gcc/x86_64-suse-linux/7.3.0;/opt/gcc/7.3.0/snos/lib64;/lib64;/usr/lib64;/opt/gcc/7.3.0/snos/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Intel-18.0.2.20180210.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Intel-18.0.2.20180210.output
index 621284418..1a3b736b0 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Intel-18.0.2.20180210.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Intel-18.0.2.20180210.output
@@ -1,2 +1,2 @@
-libs=imf;svml;irng;stdc++;m;ipgo;decimal;cilkrts;stdc++;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c
+libs=imf;svml;irng;stdc\+\+;m;ipgo;decimal;cilkrts;stdc\+\+;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c
dirs=/opt/intel/2018.2.199/compilers_and_libraries_2018/linux/mkl/lib/intel64;/opt/intel/2018.2.199/compilers_and_libraries_2018.2.199/linux/compiler/lib/intel64_lin;/opt/gcc/6.3.0/snos/lib/gcc/x86_64-suse-linux/6.3.0;/opt/gcc/6.3.0/snos/lib64;/lib64;/usr/lib64;/opt/gcc/6.3.0/snos/lib;/lib;/usr/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-8.7.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-8.7.output
index 9828bf3cf..3b26f407f 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-8.7.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-8.7.output
@@ -1,2 +1,2 @@
-libs=AtpSigHandler;AtpSigHCommData;rca;sci_cray_mpi_mp;sci_cray_mp;mpich_cray;mpichf90_cray;pgas-dmapp;quadmath;omp;craymp;modules;fi;craymath;f;u;csup;atomic;gfortran;tcmalloc_minimal;stdc++;pthread;c;csup;m;gcc
+libs=AtpSigHandler;AtpSigHCommData;rca;sci_cray_mpi_mp;sci_cray_mp;mpich_cray;mpichf90_cray;pgas-dmapp;quadmath;omp;craymp;modules;fi;craymath;f;u;csup;atomic;gfortran;tcmalloc_minimal;stdc\+\+;pthread;c;csup;m;gcc
dirs=/opt/gcc/6.1.0/snos/lib64;/opt/cray/pe/libsci/18.07.1/CRAY/8.6/x86_64/lib;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.3/gni/mpich-cray/8.6/lib;/opt/cray/rca/2.2.16-6.0.5.0_15.34__g5e09e6d.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/8.7.4/cce/x86_64/lib;/usr/lib64;/lib64;/opt/gcc/6.1.0/snos/lib/gcc/x86_64-suse-linux/6.1.0;/opt/cray/pe/cce/8.7.4/binutils/x86_64/x86_64-unknown-linux-gnu/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-9.0-hlist-ad.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-9.0-hlist-ad.output
index 46754080f..d15e5a7f0 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-9.0-hlist-ad.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-9.0-hlist-ad.output
@@ -1,2 +1,2 @@
-libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;mpichf90_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;gfortran;tcmalloc_minimal;cray-c++-rts;stdc++;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc
+libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;mpichf90_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;gfortran;tcmalloc_minimal;cray-c\+\+-rts;stdc\+\+;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc
dirs=/opt/gcc/8.1.0/snos/lib64;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.8/gni/mpich-cray/9.0/lib;/opt/cray/pe/libsci/19.06.1/CRAY/9.0/x86_64/lib;/opt/cray/rca/2.2.18-6.0.7.0_33.3__g2aa4f39.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/9.0.0/cce/x86_64/lib;/usr/lib64;/lib64;/opt/cray/pe/cce/9.0.0/cce-clang/x86_64/lib/clang/9.0.0/lib/linux;/opt/gcc/8.1.0/snos/lib/gcc/x86_64-suse-linux/8.1.0;/opt/cray/pe/cce/9.0.0/binutils/x86_64/x86_64-unknown-linux-gnu/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin-CXX-AppleClang-8.0.0.8000042.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin-CXX-AppleClang-8.0.0.8000042.output
index f75637c57..47a362a53 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin-CXX-AppleClang-8.0.0.8000042.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin-CXX-AppleClang-8.0.0.8000042.output
@@ -1,2 +1,2 @@
-libs=c++
+libs=c\+\+
dirs=/usr/lib;/usr/local/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output
index f75637c57..47a362a53 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output
@@ -1,2 +1,2 @@
-libs=c++
+libs=c\+\+
dirs=/usr/lib;/usr/local/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/freebsd-CXX-Clang-3.3.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/freebsd-CXX-Clang-3.3.0.output
index b0b8e25b5..18d7cd173 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/freebsd-CXX-Clang-3.3.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/freebsd-CXX-Clang-3.3.0.output
@@ -1,2 +1,2 @@
-libs=c++;m;gcc;gcc_s;c;gcc;gcc_s
+libs=c\+\+;m;gcc;gcc_s;c;gcc;gcc_s
dirs=/usr/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-10.2.1-static-libgcc.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-10.2.1-static-libgcc.output
new file mode 100644
index 000000000..8bcd8b239
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-10.2.1-static-libgcc.output
@@ -0,0 +1,3 @@
+libs=gcc;c;gcc
+dirs=/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib
+library_arch=x86_64-linux-gnu
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output
index e61329003..d78c9f48a 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output
@@ -1,3 +1,3 @@
-libs=imf;svml;irng;m;ipgo;decimal;cilkrts;stdc++;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c
+libs=imf;svml;irng;m;ipgo;decimal;cilkrts;stdc\+\+;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c
dirs=/opt/intel/compilers_and_libraries_2018.0.128/linux/ipp/lib/intel64;/opt/intel/compilers_and_libraries_2018.0.128/linux/compiler/lib/intel64_lin;/opt/intel/compilers_and_libraries_2018.0.128/linux/mkl/lib/intel64_lin;/opt/intel/compilers_and_libraries_2018.0.128/linux/tbb/lib/intel64/gcc4.7;/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib;/lib
library_arch=
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output
index 813457aef..be6b906d0 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output
@@ -1,3 +1,3 @@
-libs=cudadevrt;cudart_static;rt;pthread;dl;stdc++;m;gcc_s;gcc;c;gcc_s;gcc
+libs=cudadevrt;cudart_static;rt;pthread;dl;stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc
dirs=/usr/local/cuda/targets/x86_64-linux/lib/stubs;/usr/local/cuda/targets/x86_64-linux/lib;/usr/lib/gcc/x86_64-linux-gnu/8;/usr/lib/x86_64-linux-gnu;/lib/x86_64-linux-gnu;/lib64;/usr/lib;/usr/lib/llvm-8/lib;/lib
library_arch=x86_64-linux-gnu
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output
index 261785c96..d3f362754 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output
@@ -1,3 +1,3 @@
-libs=cudadevrt;cudart_static;rt;pthread;dl;xlopt;xl;ibmc++;stdc++;m;dl;gcc_s;gcc;pthread;m;c;gcc_s;gcc
+libs=cudadevrt;cudart_static;rt;pthread;dl;xlopt;xl;ibmc\+\+;stdc\+\+;m;dl;gcc_s;gcc;pthread;m;c;gcc_s;gcc
dirs=/sw/summit/cuda/10.1.168/targets/ppc64le-linux/lib/stubs;/sw/summit/cuda/10.1.168/targets/ppc64le-linux/lib;/autofs/nccs-svm1_sw/summit/.swci/1-compute/opt/spack/20180914/linux-rhel7-ppc64le/xl-16.1.1-3/spectrum-mpi-10.3.0.1-20190611-aqjt3jo53mogrrhcrd2iufr435azcaha/lib;/autofs/nccs-svm1_sw/summit/.swci/1-compute/opt/spack/20180914/linux-rhel7-ppc64le/gcc-4.8.5/darshan-runtime-3.1.7-csygoqyym3m3ysoaperhxlhoiluvpa2u/lib;/autofs/nccs-svm1_sw/summit/xl/16.1.1-3/xlsmp/5.1.1/lib;/autofs/nccs-svm1_sw/summit/xl/16.1.1-3/xlmass/9.1.1/lib;/autofs/nccs-svm1_sw/summit/xl/16.1.1-3/xlC/16.1.1/lib;/usr/lib/gcc/ppc64le-redhat-linux/4.8.5;/usr/lib64;/lib64;/autofs/nccs-svm1_sw/peak/.swci/1-compute/opt/spack/20180914/linux-rhel7-ppc64le/gcc-4.8.5/darshan-runtime-3.1.7-ytwv7xbkub6mqnpvygdthwqa7mhjqbc5/lib;/usr/lib
library_arch=
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output
index 275fe40c9..958f41daa 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output
@@ -1,3 +1,3 @@
-libs=cudadevrt;cudart_static;rt;pthread;dl;stdc++;m;gcc_s;gcc;c;gcc_s;gcc
+libs=cudadevrt;cudart_static;rt;pthread;dl;stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc
dirs=/usr/lib/x86_64-linux-gnu/stubs;/usr/lib/gcc/x86_64-linux-gnu/5;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib
library_arch=x86_64-linux-gnu
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output
new file mode 100644
index 000000000..d38dfeef9
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output
@@ -0,0 +1,3 @@
+libs=/usr/lib/gcc/x86_64-linux-gnu/10/libstdc\+\+.a;m;gcc_s;gcc;c;gcc_s;gcc
+dirs=/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib
+library_arch=x86_64-linux-gnu
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output
index 4957f5cd3..f87ecff78 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output
@@ -1,3 +1,3 @@
-libs=stdc++;m;gcc_s;gcc;c;gcc_s;gcc
+libs=stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc
dirs=/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib
library_arch=x86_64-linux-gnu
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output
index 678a196f5..832f21867 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output
@@ -1,3 +1,3 @@
-libs=imf;svml;irng;stdc++;m;ipgo;decimal;cilkrts;stdc++;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c
+libs=imf;svml;irng;stdc\+\+;m;ipgo;decimal;cilkrts;stdc\+\+;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c
dirs=/opt/intel/compilers_and_libraries_2018.0.128/linux/ipp/lib/intel64;/opt/intel/compilers_and_libraries_2018.0.128/linux/compiler/lib/intel64_lin;/opt/intel/compilers_and_libraries_2018.0.128/linux/mkl/lib/intel64_lin;/opt/intel/compilers_and_libraries_2018.0.128/linux/tbb/lib/intel64/gcc4.7;/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib;/lib
library_arch=
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-NVHPC-21.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-NVHPC-21.1.0.output
index e7f7d0536..5e93f6d33 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-NVHPC-21.1.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-NVHPC-21.1.0.output
@@ -1,3 +1,3 @@
-libs=atomic;nvhpcatm;stdc++;nvomp;dl;nvhpcatm;atomic;pthread;nvcpumath;nsnvc;nvc;m;gcc;c;gcc;gcc_s
+libs=atomic;nvhpcatm;stdc\+\+;nvomp;dl;nvhpcatm;atomic;pthread;nvcpumath;nsnvc;nvc;m;gcc;c;gcc;gcc_s
dirs=/opt/nvidia/hpc_sdk/Linux_x86_64/21.1/compilers/lib;/usr/lib64;/usr/lib/gcc/x86_64-linux-gnu/9
library_arch=x86_64-linux-gnu
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output
index cd15054cb..0e9596159 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output
@@ -1,3 +1,3 @@
-libs=atomic;pgatm;stdc++;pgmp;numa;pthread;pgmath;nspgc;pgc;m;gcc;c;gcc;gcc_s
+libs=atomic;pgatm;stdc\+\+;pgmp;numa;pthread;pgmath;nspgc;pgc;m;gcc;c;gcc;gcc_s
dirs=/mnt/pgi/linux86-64/18.10/lib;/usr/lib64;/usr/lib/gcc/x86_64-linux-gnu/7
library_arch=x86_64-linux-gnu
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output
index 45c55657f..34cab2ea5 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output
@@ -1,3 +1,3 @@
-libs=xlopt;xl;ibmc++;xlopt;xl;stdc++;m;dl;gcc_s;gcc;m;c;gcc_s;gcc;dl;gcc_s;gcc;m;c;gcc_s;gcc
+libs=xlopt;xl;ibmc\+\+;xlopt;xl;stdc\+\+;m;dl;gcc_s;gcc;m;c;gcc_s;gcc;dl;gcc_s;gcc;m;c;gcc_s;gcc
dirs=/soft/compilers/ibmcmp-oct2017/xlsmp/bg/3.1/lib64;/soft/compilers/ibmcmp-oct2017/xlmass/bg/7.3/lib64;/soft/compilers/ibmcmp-oct2017/vac/bg/12.1/lib64;/soft/compilers/ibmcmp-oct2017/vacpp/bg/12.1/lib64;/usr/lib/gcc/ppc64-redhat-linux/4.4.7;/usr/lib64;/lib64;/usr/lib
library_arch=
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output
index 9d649ecba..c754bda36 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output
@@ -1,3 +1,3 @@
-libs=xlopt;xl;ibmc++;stdc++;m;dl;gcc_s;gcc;pthread;m;c;gcc_s;gcc
+libs=xlopt;xl;ibmc\+\+;stdc\+\+;m;dl;gcc_s;gcc;pthread;m;c;gcc_s;gcc
dirs=/opt/ibm/xlsmp/5.1.0/lib;/opt/ibm/xlmass/9.1.0/lib;/opt/ibm/xlC/16.1.0/lib;/usr/lib/gcc/ppc64le-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib
library_arch=
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output
new file mode 100644
index 000000000..edeb20c5a
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output
@@ -0,0 +1,3 @@
+libs=/usr/lib/gcc/x86_64-linux-gnu/10/libgfortran.a;m;gcc_s;gcc;quadmath;m;gcc_s;gcc;c;gcc_s;gcc
+dirs=/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib
+library_arch=x86_64-linux-gnu
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output
index a7c14d272..848e8c0e0 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output
@@ -1,3 +1,3 @@
-libs=atomic;pgatm;stdc++;pgmp;numa;pthread;pgmath;nspgc;pgc;m;gcc;c;gcc;gcc_s
+libs=atomic;pgatm;stdc\+\+;pgmp;numa;pthread;pgmath;nspgc;pgc;m;gcc;c;gcc;gcc_s
dirs=/mnt/pgi/linux86-64/18.10/lib;/usr/lib64;/usr/lib/gcc/x86_64-linux-gnu/7
library_arch=
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output
index 45c55657f..34cab2ea5 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output
@@ -1,3 +1,3 @@
-libs=xlopt;xl;ibmc++;xlopt;xl;stdc++;m;dl;gcc_s;gcc;m;c;gcc_s;gcc;dl;gcc_s;gcc;m;c;gcc_s;gcc
+libs=xlopt;xl;ibmc\+\+;xlopt;xl;stdc\+\+;m;dl;gcc_s;gcc;m;c;gcc_s;gcc;dl;gcc_s;gcc;m;c;gcc_s;gcc
dirs=/soft/compilers/ibmcmp-oct2017/xlsmp/bg/3.1/lib64;/soft/compilers/ibmcmp-oct2017/xlmass/bg/7.3/lib64;/soft/compilers/ibmcmp-oct2017/vac/bg/12.1/lib64;/soft/compilers/ibmcmp-oct2017/vacpp/bg/12.1/lib64;/usr/lib/gcc/ppc64-redhat-linux/4.4.7;/usr/lib64;/lib64;/usr/lib
library_arch=
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/mingw.org-CXX-GNU-4.9.3.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/mingw.org-CXX-GNU-4.9.3.output
index 5e79cc1ad..7852bfd2b 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/mingw.org-CXX-GNU-4.9.3.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/mingw.org-CXX-GNU-4.9.3.output
@@ -1,2 +1,2 @@
-libs=stdc++;mingw32;gcc_s;gcc;moldname;mingwex;advapi32;shell32;user32;kernel32;mingw32;gcc_s;gcc;moldname;mingwex
+libs=stdc\+\+;mingw32;gcc_s;gcc;moldname;mingwex;advapi32;shell32;user32;kernel32;mingw32;gcc_s;gcc;moldname;mingwex
dirs=C:/DoesNotExist/mingw/lib/gcc/mingw32/4.9.3;C:/DoesNotExist/mingw/lib/gcc;C:/DoesNotExist/mingw/mingw32/lib;C:/DoesNotExist/mingw/lib
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd-CXX-GNU-4.8.5.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd-CXX-GNU-4.8.5.output
index d747e5b87..c6a098ef9 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd-CXX-GNU-4.8.5.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd-CXX-GNU-4.8.5.output
@@ -1,2 +1,2 @@
-libs=stdc++;m;gcc_s;gcc;c;gcc_s;gcc
+libs=stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc
dirs=
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd_nostdinc-CXX-GNU-4.8.5.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd_nostdinc-CXX-GNU-4.8.5.output
index d747e5b87..c6a098ef9 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd_nostdinc-CXX-GNU-4.8.5.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd_nostdinc-CXX-GNU-4.8.5.output
@@ -1,2 +1,2 @@
-libs=stdc++;m;gcc_s;gcc;c;gcc_s;gcc
+libs=stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc
dirs=
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/openbsd-CXX-Clang-5.0.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/openbsd-CXX-Clang-5.0.1.output
index 4158973ca..711225ce6 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/openbsd-CXX-Clang-5.0.1.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/openbsd-CXX-Clang-5.0.1.output
@@ -1,2 +1,2 @@
-libs=c++;c++abi;pthread;m;compiler_rt;c;compiler_rt
+libs=c\+\+;c\+\+abi;pthread;m;compiler_rt;c;compiler_rt
dirs=/usr/lib
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index ea94a5b89..3363a579e 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -23,10 +23,13 @@ function(run_cmake test)
endif()
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} platform_name)
+ #remove all additional bits from cygwin/msys name
if(platform_name MATCHES cygwin)
- #remove all additional bits from cygwin name
set(platform_name cygwin)
endif()
+ if(platform_name MATCHES msys)
+ set(platform_name msys)
+ endif()
foreach(o out err)
if(RunCMake-std${o}-file AND EXISTS ${top_src}/${RunCMake-std${o}-file})
@@ -64,15 +67,6 @@ function(run_cmake test)
else()
include(${top_src}/${test}-prep.cmake OPTIONAL)
endif()
- if(NOT DEFINED RunCMake_TEST_OPTIONS)
- set(RunCMake_TEST_OPTIONS "")
- endif()
- if(APPLE)
- list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0025=NEW)
- endif()
- if(RunCMake_MAKE_PROGRAM)
- list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}")
- endif()
if(RunCMake_TEST_OUTPUT_MERGE)
set(actual_stderr_var actual_stdout)
set(actual_stderr "")
@@ -91,50 +85,51 @@ function(run_cmake test)
else()
set(maybe_input_file "")
endif()
- if(RunCMake_TEST_COMMAND)
- if(NOT RunCMake_TEST_COMMAND_WORKING_DIRECTORY)
- set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ if(NOT RunCMake_TEST_COMMAND)
+ if(NOT DEFINED RunCMake_TEST_OPTIONS)
+ set(RunCMake_TEST_OPTIONS "")
endif()
- execute_process(
- COMMAND ${RunCMake_TEST_COMMAND}
- WORKING_DIRECTORY "${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}"
- OUTPUT_VARIABLE actual_stdout
- ERROR_VARIABLE ${actual_stderr_var}
- RESULT_VARIABLE actual_result
- ENCODING UTF8
- ${maybe_timeout}
- ${maybe_input_file}
- )
- else()
- if(RunCMake_GENERATOR_INSTANCE)
- set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${RunCMake_GENERATOR_INSTANCE}")
- else()
- set(_D_CMAKE_GENERATOR_INSTANCE "")
+ if(APPLE)
+ list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0025=NEW)
+ endif()
+ if(RunCMake_MAKE_PROGRAM)
+ list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}")
endif()
+ set(RunCMake_TEST_COMMAND ${CMAKE_COMMAND})
if(NOT RunCMake_TEST_NO_SOURCE_DIR)
- set(maybe_source_dir "${RunCMake_TEST_SOURCE_DIR}")
- else()
- set(maybe_source_dir "")
+ list(APPEND RunCMake_TEST_COMMAND "${RunCMake_TEST_SOURCE_DIR}")
+ endif()
+ list(APPEND RunCMake_TEST_COMMAND -G "${RunCMake_GENERATOR}")
+ if(RunCMake_GENERATOR_PLATFORM)
+ list(APPEND RunCMake_TEST_COMMAND -A "${RunCMake_GENERATOR_PLATFORM}")
+ endif()
+ if(RunCMake_GENERATOR_TOOLSET)
+ list(APPEND RunCMake_TEST_COMMAND -T "${RunCMake_GENERATOR_TOOLSET}")
+ endif()
+ if(RunCMake_GENERATOR_INSTANCE)
+ list(APPEND RunCMake_TEST_COMMAND "-DCMAKE_GENERATOR_INSTANCE=${RunCMake_GENERATOR_INSTANCE}")
endif()
- execute_process(
- COMMAND ${CMAKE_COMMAND}
- ${maybe_source_dir}
- -G "${RunCMake_GENERATOR}"
- -A "${RunCMake_GENERATOR_PLATFORM}"
- -T "${RunCMake_GENERATOR_TOOLSET}"
- ${_D_CMAKE_GENERATOR_INSTANCE}
- -DRunCMake_TEST=${test}
- --no-warn-unused-cli
- ${RunCMake_TEST_OPTIONS}
- WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}"
- OUTPUT_VARIABLE actual_stdout
- ERROR_VARIABLE ${actual_stderr_var}
- RESULT_VARIABLE actual_result
- ENCODING UTF8
- ${maybe_timeout}
- ${maybe_input_file}
+ list(APPEND RunCMake_TEST_COMMAND
+ -DRunCMake_TEST=${test}
+ --no-warn-unused-cli
)
+ else()
+ set(RunCMake_TEST_OPTIONS "")
endif()
+ if(NOT RunCMake_TEST_COMMAND_WORKING_DIRECTORY)
+ set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ endif()
+ execute_process(
+ COMMAND ${RunCMake_TEST_COMMAND}
+ ${RunCMake_TEST_OPTIONS}
+ WORKING_DIRECTORY "${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}"
+ OUTPUT_VARIABLE actual_stdout
+ ERROR_VARIABLE ${actual_stderr_var}
+ RESULT_VARIABLE actual_result
+ ENCODING UTF8
+ ${maybe_timeout}
+ ${maybe_input_file}
+ )
set(msg "")
if(NOT "${actual_result}" MATCHES "${expect_result}")
string(APPEND msg "Result is [${actual_result}], not [${expect_result}].\n")
@@ -160,6 +155,7 @@ function(run_cmake test)
"|contact PGI Sales at"
"|[^\n]*install_name_tool: warning: changes being made to the file will invalidate the code signature in:"
+ "|[^\n]*xcodebuild[^\n]*DVTPlugInManager"
"|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type"
"|[^\n]*objc[^\n]*: Class AMSupportURL[^\n]* One of the two will be used. Which one is undefined."
"|[^\n]*is a member of multiple groups"
@@ -191,14 +187,18 @@ function(run_cmake test)
if(RunCMake_TEST_FAILED)
set(msg "${RunCMake_TEST_FAILED}\n${msg}")
endif()
- if(msg AND RunCMake_TEST_COMMAND)
+ if(msg)
string(REPLACE ";" "\" \"" command "\"${RunCMake_TEST_COMMAND}\"")
+ if(RunCMake_TEST_OPTIONS)
+ string(REPLACE ";" "\" \"" options "\"${RunCMake_TEST_OPTIONS}\"")
+ string(APPEND command " ${options}")
+ endif()
string(APPEND msg "Command was:\n command> ${command}\n")
endif()
if(msg)
string(REGEX REPLACE "\n" "\n actual-out> " actual_out " actual-out> ${actual_stdout}")
string(REGEX REPLACE "\n" "\n actual-err> " actual_err " actual-err> ${actual_stderr}")
- message(SEND_ERROR "${test} - FAILED:\n"
+ message(SEND_ERROR "${test}${RunCMake_TEST_VARIANT_DESCRIPTION} - FAILED:\n"
"${msg}"
"${expect_out}"
"Actual stdout:\n${actual_out}\n"
@@ -206,7 +206,7 @@ function(run_cmake test)
"Actual stderr:\n${actual_err}\n"
)
else()
- message(STATUS "${test} - PASSED")
+ message(STATUS "${test}${RunCMake_TEST_VARIANT_DESCRIPTION} - PASSED")
endif()
endfunction()
diff --git a/Tests/RunCMake/RunCTest.cmake b/Tests/RunCMake/RunCTest.cmake
index 98fdf20ac..59db395e1 100644
--- a/Tests/RunCMake/RunCTest.cmake
+++ b/Tests/RunCMake/RunCTest.cmake
@@ -11,10 +11,13 @@ function(run_ctest CASE_NAME)
endif()
configure_file(${RunCMake_SOURCE_DIR}/CMakeLists.txt.in
${RunCMake_BINARY_DIR}/${CASE_NAME}/CMakeLists.txt @ONLY)
+ if(NOT DEFINED RunCTest_VERBOSE_FLAG)
+ set(RunCTest_VERBOSE_FLAG "-V")
+ endif()
run_cmake_command(${CASE_NAME} ${CMAKE_CTEST_COMMAND}
-C Debug
-S ${RunCMake_BINARY_DIR}/${CASE_NAME}/test.cmake
- -V
+ ${RunCTest_VERBOSE_FLAG}
--output-log ${RunCMake_BINARY_DIR}/${CASE_NAME}-build/testOutput.log
--no-compress-output
${ARGN}
diff --git a/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt b/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt
index 77c4afd08..9145a56e6 100644
--- a/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt
+++ b/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt
@@ -3,7 +3,7 @@ CMake Error at NotObjlibTarget.cmake:[0-9]+ \(file\):
\$<TARGET_OBJECTS:IFaceLib>
- Objects of target "IFaceLib" referenced but is not an allowed library types
- \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\).
+ Objects of target "IFaceLib" referenced but is not one of the allowed
+ target types \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\).
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake b/Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake
new file mode 100644
index 000000000..be07dc318
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake
@@ -0,0 +1,2 @@
+set(C 1)
+set(CXX 1)
diff --git a/Tests/RunCMake/ToolchainFile/LangVars.cmake b/Tests/RunCMake/ToolchainFile/LangVars.cmake
new file mode 100644
index 000000000..169e639f5
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/LangVars.cmake
@@ -0,0 +1,7 @@
+foreach(test_language C CXX)
+ enable_language(${test_language})
+ if(DEFINED CMAKE_${test_language}_STANDARD_DEFAULT
+ AND NOT CMAKE_${test_language}_COMPILE_FEATURES)
+ message(FATAL_ERROR "Compile features not found for ${test_language}")
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
index 659523c42..304c10525 100644
--- a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
@@ -9,6 +9,7 @@ run_cmake_toolchain(CallEnableLanguage)
run_cmake_toolchain(CallProject)
run_cmake_toolchain(CheckLanguage)
run_cmake_toolchain(FlagsInit)
+run_cmake_toolchain(LangVars)
run_cmake_toolchain(LinkFlagsInit)
function(run_IncludeDirectories)
diff --git a/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake
index 9a38b957f..1ce723b40 100644
--- a/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake
@@ -5,10 +5,6 @@ function(run_transform_depfile name)
run_cmake_command(${name}-gcc
${CMAKE_COMMAND} -E cmake_transform_depfile "${RunCMake_GENERATOR}" gccdepfile "${RunCMake_SOURCE_DIR}" "${RunCMake_SOURCE_DIR}/subdir" "${RunCMake_BINARY_DIR}" "${RunCMake_BINARY_DIR}/subdir" "${CMAKE_CURRENT_LIST_DIR}/${name}.d" out.d
)
- set(RunCMake-check-file vstlog.cmake)
- run_cmake_command(${name}-tlog
- ${CMAKE_COMMAND} -E cmake_transform_depfile "${RunCMake_GENERATOR}" vstlog "${RunCMake_SOURCE_DIR}" "${RunCMake_SOURCE_DIR}/subdir" "${RunCMake_BINARY_DIR}" "${RunCMake_BINARY_DIR}/subdir" "${CMAKE_CURRENT_LIST_DIR}/${name}.d" out.tlog
- )
endfunction()
if(WIN32)
diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt
deleted file mode 100644
index 70bac5da2..000000000
--- a/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-^subdir/out1|/home/build/out2
-subdir/in1
-/home/build/in2
-^subdir/out3|/home/build/out4
-subdir/in3
-/home/build/in4
diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt
deleted file mode 100644
index 09f9e9711..000000000
--- a/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-^subdir\out1|C:\build\out2
-subdir\in1
-C:\build\in2
-^subdir\out3|C:\build\out4
-subdir\in3
-C:\build\in4
diff --git a/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt b/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt
deleted file mode 100644
index 0cfbf0888..000000000
--- a/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-2
diff --git a/Tests/RunCMake/TransformDepfile/vstlog.cmake b/Tests/RunCMake/TransformDepfile/vstlog.cmake
deleted file mode 100644
index afa78d05c..000000000
--- a/Tests/RunCMake/TransformDepfile/vstlog.cmake
+++ /dev/null
@@ -1,16 +0,0 @@
-if(EXISTS "${RunCMake_SOURCE_DIR}/${name}.tlog.txt")
- file(READ "${RunCMake_SOURCE_DIR}/${name}.tlog.txt" expected_contents)
-
- if(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.tlog")
- file(READ "${RunCMake_TEST_BINARY_DIR}/out.tlog" actual_contents)
- if(NOT actual_contents STREQUAL expected_contents)
- string(REPLACE "\n" "\n " p_expected_contents "${expected_contents}")
- string(REPLACE "\n" "\n " p_actual_contents "${actual_contents}")
- string(APPEND RunCMake_TEST_FAILED "Expected contents of ${RunCMake_TEST_BINARY_DIR}/out.tlog:\n ${p_expected_contents}\nActual contents:\n ${p_actual_contents}")
- endif()
- else()
- string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.tlog should exist\n")
- endif()
-elseif(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.tlog")
- string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.tlog should not exist\n")
-endif()
diff --git a/Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt b/Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt
new file mode 100644
index 000000000..2afdc4f49
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0078-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0078 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/UseSWIG/CMP0122-NEW-check.cmake b/Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake
new file mode 100644
index 000000000..a26c27842
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake
@@ -0,0 +1,10 @@
+
+cmake_policy(VERSION 3.1)
+
+file(STRINGS "${RunCMake_TEST_BINARY_DIR}/CMP0122-library-name.txt" prefixes)
+
+list(GET prefixes 0 std_prefix)
+list(GET prefixes 1 lib_prefix)
+if (NOT std_prefix STREQUAL lib_prefix)
+ string (APPEND RunCMake_TEST_FAILED "\nFound prefix: '${lib_prefix}', expected: '${std_prefix}'.")
+endif()
diff --git a/Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake b/Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake
new file mode 100644
index 000000000..fecb7dba4
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0122 NEW)
+include(CMP0122-common.cmake)
diff --git a/Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake b/Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake
new file mode 100644
index 000000000..01657d0c5
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake
@@ -0,0 +1,10 @@
+
+cmake_policy(VERSION 3.1)
+
+file(STRINGS "${RunCMake_TEST_BINARY_DIR}/CMP0122-library-name.txt" prefixes)
+
+list(GET prefixes 1 lib_prefix)
+if (lib_prefix)
+ # prefix must be empty
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected prefix: '${lib_prefix}'.")
+endif()
diff --git a/Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake b/Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake
new file mode 100644
index 000000000..a787b6849
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0122 OLD)
+include(CMP0122-common.cmake)
diff --git a/Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt b/Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt
new file mode 100644
index 000000000..37c4fbd7a
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt
@@ -0,0 +1,10 @@
+CMake Warning \(dev\) at .*/Modules/UseSWIG.cmake:[0-9]+ \(message\):
+ Policy CMP0122 is not set: UseSWIG use standard library name conventions
+ for csharp language\. Run "cmake --help-policy CMP0122" for policy details\.
+ Use the cmake_policy command to set the policy and suppress this warning\.
+
+Call Stack \(most recent call first\):
+ CMP0122-common.cmake:9 \(swig_add_library\)
+ CMP0122-WARN.cmake:1 \(include\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake b/Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake
new file mode 100644
index 000000000..5d571aa3e
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake
@@ -0,0 +1 @@
+include(CMP0122-common.cmake)
diff --git a/Tests/RunCMake/UseSWIG/CMP0122-common.cmake b/Tests/RunCMake/UseSWIG/CMP0122-common.cmake
new file mode 100644
index 000000000..be880ec24
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMP0122-common.cmake
@@ -0,0 +1,12 @@
+
+cmake_policy(SET CMP0078 NEW)
+cmake_policy(SET CMP0086 NEW)
+
+set(SWIG_EXECUTABLE "swig")
+set(SWIG_DIR "/swig")
+include(UseSWIG)
+
+swig_add_library(example LANGUAGE csharp TYPE SHARED SOURCES example.i)
+
+file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/CMP0122-library-name.txt"
+ CONTENT "${CMAKE_SHARED_LIBRARY_PREFIX}\n$<TARGET_FILE_PREFIX:example>\n")
diff --git a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake
index 6acf7199c..c7a118ffc 100644
--- a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake
+++ b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake
@@ -23,3 +23,7 @@ if (CMake_TEST_FindPython)
run_cmake_target(CMP0086-NEW build example)
endif()
+
+run_cmake(CMP0122-WARN)
+run_cmake(CMP0122-OLD)
+run_cmake(CMP0122-NEW)
diff --git a/Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in b/Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in
new file mode 100644
index 000000000..63e5a5ce7
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+//General Information about an assembly is controlled through the following
+//set of attributes. Change these attribute values to modify the information
+//associated with an assembly.
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake
index 80d76e40c..9c9409cc4 100644
--- a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake
+++ b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake
@@ -13,6 +13,7 @@ set(SOURCE_GROUPS_TO_FIND
"CSharpSourceGroup\\\\nested\\\\baz\\.cs"
"CSharpSourceGroup\\\\images\\\\empty\\.bmp"
"VsCsharpSourceGroup\\.png"
+ "AssemblyInfo\\.cs"
)
foreach(GROUP_NAME IN LISTS SOURCE_GROUPS_TO_FIND)
diff --git a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake
index 510d71294..b67868f77 100644
--- a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake
+++ b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake
@@ -20,3 +20,11 @@ add_library(VsCsharpSourceGroup SHARED ${SRC_FILES} ${IMAGE_FILES} ${RESOURCE_FI
source_group("CSharpSourceGroup" FILES ${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/foo.cs)
source_group("CSharpSourceGroup/nested" FILES ${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/nested/baz.cs)
source_group("Images" FILES ${IMAGE_FILES})
+
+# Test covering CMake Issue 22104.
+# Basically there should not be any link tags for files in the binary directory.
+include(CSharpUtilities)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/cmake/AssemblyInfo.cs.in" "Properties/AssemblyInfo.cs")
+
+target_sources(VsCsharpSourceGroup PRIVATE "Properties/AssemblyInfo.cs")
+csharp_set_designer_cs_properties("Properties/AssemblyInfo.cs")
diff --git a/Tests/RunCMake/WriteBasicConfigVersionFile/LeadingZeroes.cmake b/Tests/RunCMake/WriteBasicConfigVersionFile/LeadingZeroes.cmake
new file mode 100644
index 000000000..9f4674c2e
--- /dev/null
+++ b/Tests/RunCMake/WriteBasicConfigVersionFile/LeadingZeroes.cmake
@@ -0,0 +1,898 @@
+# Hard-code architecture for test without a real compiler.
+set(CMAKE_SIZEOF_VOID_P 4)
+
+include(WriteBasicConfigVersionFile)
+
+set(COMPATIBILITIES AnyNewerVersion
+ SameMajorVersion
+ SameMinorVersion
+ ExactVersion
+ )
+
+function(TEST_WRITE_BASIC_CONFIG_VERSION_FILE_PREPARE _version_installed)
+ set(_same_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
+ set(_no_CMAKE_SIZEOF_VOID_P "")
+ math(EXPR _diff_CMAKE_SIZEOF_VOID_P "${CMAKE_SIZEOF_VOID_P} + 1")
+ foreach(_compat ${COMPATIBILITIES})
+ set(_pkg ${_compat}${_version_installed})
+ string(REPLACE "." "" _pkg ${_pkg})
+ set(_filename "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}ConfigVersion.cmake")
+ set(_filename_novoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}NoVoidConfigVersion.cmake")
+ set(_filename_diffvoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}DiffVoidConfigVersion.cmake")
+
+ set(CMAKE_SIZEOF_VOID_P ${_same_CMAKE_SIZEOF_VOID_P})
+ write_basic_config_version_file("${_filename}"
+ VERSION ${_version_installed}
+ COMPATIBILITY ${_compat})
+
+ # Test that an empty CMAKE_SIZEOF_VOID_P is accepted:
+ set(CMAKE_SIZEOF_VOID_P ${_no_CMAKE_SIZEOF_VOID_P})
+ write_basic_config_version_file("${_filename_novoid}"
+ VERSION ${_version_installed}
+ COMPATIBILITY ${_compat})
+
+ # Test that a different CMAKE_SIZEOF_VOID_P results in
+ # PACKAGE_VERSION_UNSUITABLE
+ set(CMAKE_SIZEOF_VOID_P ${_diff_CMAKE_SIZEOF_VOID_P})
+ write_basic_config_version_file("${_filename_diffvoid}"
+ VERSION ${_version_installed}
+ COMPATIBILITY ${_compat})
+ endforeach()
+endfunction()
+
+macro(TEST_WRITE_BASIC_CONFIG_VERSION_FILE_CHECK _filename)
+ include("${_filename}")
+
+ message(STATUS "_expected_compatible: ${_expected_compatible}")
+ message(STATUS "_expected_unsuitable: ${_expected_unsuitable}")
+ if(_expected_compatible AND NOT PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Did not find package with version ${_version_installed} (${_version_requested} was requested)!")
+ elseif(NOT _expected_compatible AND PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Found package with version ${_version_installed}, but ${_version_requested} was requested!")
+ endif()
+
+ if(${_expected_unsuitable} AND NOT PACKAGE_VERSION_UNSUITABLE)
+ message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, although it should not be!")
+ elseif(NOT ${_expected_unsuitable} AND PACKAGE_VERSION_UNSUITABLE)
+ message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE not set, although it should be!")
+ endif()
+
+ unset(PACKAGE_VERSION_COMPATIBLE)
+ unset(PACKAGE_VERSION_EXACT)
+ unset(PACKAGE_VERSION_UNSUITABLE)
+endmacro()
+
+function(TEST_WRITE_BASIC_CONFIG_VERSION_FILE _version_installed
+ _version_requested
+ _expected_compatible_AnyNewerVersion
+ _expected_compatible_SameMajorVersion
+ _expected_compatible_SameMinorVersion
+ _expected_compatible_ExactVersion)
+ if("${_version_requested}" MATCHES [[^([0-9]+(\.[0-9]+)*)\.\.\.(<)?([0-9]+(\.[0-9]+)*)$]])
+ set (_compatibilities ${COMPATIBILITIES})
+ # ExactVersion must not be tested
+ list(POP_BACK _compatibilities)
+ set(PACKAGE_FIND_VERSION_RANGE TRUE)
+ set(PACKAGE_FIND_VERSION_RANGE_MIN INCLUDE)
+ if ("${CMAKE_MATCH_3}" STREQUAL "<")
+ set(PACKAGE_FIND_VERSION_RANGE_MAX EXCLUDE)
+ else()
+ set(PACKAGE_FIND_VERSION_RANGE_MAX INCLUDE)
+ endif()
+ set(PACKAGE_FIND_VERSION_MIN "${CMAKE_MATCH_1}")
+ set(PACKAGE_FIND_VERSION_MAX "${CMAKE_MATCH_4}")
+ if("${PACKAGE_FIND_VERSION_MIN}" MATCHES [[(^([0-9]+)(\.([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?)?)?$]])
+ set(PACKAGE_FIND_VERSION_MIN_MAJOR "${CMAKE_MATCH_2}")
+ set(PACKAGE_FIND_VERSION_MIN_MINOR "${CMAKE_MATCH_4}")
+ set(PACKAGE_FIND_VERSION_MIN_PATCH "${CMAKE_MATCH_6}")
+ set(PACKAGE_FIND_VERSION_MIN_TWEAK "${CMAKE_MATCH_8}")
+ else()
+ message(FATAL_ERROR "_version_requested (${_version_requested}) should be a version range")
+ endif()
+ set(PACKAGE_FIND_VERSION "${PACKAGE_FIND_VERSION_MIN}")
+ set(PACKAGE_FIND_VERSION_MAJOR "${PACKAGE_FIND_VERSION_MIN_MAJOR}")
+ set(PACKAGE_FIND_VERSION_MINOR "${PACKAGE_FIND_VERSION_MIN_MINOR}")
+ set(PACKAGE_FIND_VERSION_PATCH "${PACKAGE_FIND_VERSION_MIN_PATCH}")
+ set(PACKAGE_FIND_VERSION_TWEAK "${PACKAGE_FIND_VERSION_MIN_TWEAK}")
+ if("${PACKAGE_FIND_VERSION_MAX}" MATCHES [[(^([0-9]+)(\.([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?)?)?$]])
+ set(PACKAGE_FIND_VERSION_MAX_MAJOR "${CMAKE_MATCH_2}")
+ set(PACKAGE_FIND_VERSION_MAX_MINOR "${CMAKE_MATCH_4}")
+ set(PACKAGE_FIND_VERSION_MAX_PATCH "${CMAKE_MATCH_6}")
+ set(PACKAGE_FIND_VERSION_MAX_TWEAK "${CMAKE_MATCH_8}")
+ else()
+ message(FATAL_ERROR "_version_requested (${_version_requested}) should be a version range")
+ endif()
+ else()
+ set (_compatibilities ${COMPATIBILITIES})
+ set(PACKAGE_FIND_VERSION ${_version_requested})
+ if("${PACKAGE_FIND_VERSION}" MATCHES [[(^([0-9]+)(\.([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?)?)?$]])
+ set(PACKAGE_FIND_VERSION_MAJOR "${CMAKE_MATCH_2}")
+ set(PACKAGE_FIND_VERSION_MINOR "${CMAKE_MATCH_4}")
+ set(PACKAGE_FIND_VERSION_PATCH "${CMAKE_MATCH_6}")
+ set(PACKAGE_FIND_VERSION_TWEAK "${CMAKE_MATCH_8}")
+ else()
+ message(FATAL_ERROR "_version_requested (${_version_requested}) should be a version number")
+ endif()
+
+ endif()
+
+ unset(PACKAGE_VERSION_COMPATIBLE)
+ unset(PACKAGE_VERSION_EXACT)
+ unset(PACKAGE_VERSION_UNSUITABLE)
+
+ foreach(_compat ${_compatibilities})
+ set(_pkg ${_compat}${_version_installed})
+ string(REPLACE "." "" _pkg ${_pkg})
+ set(_filename "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}ConfigVersion.cmake")
+ set(_filename_novoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}NoVoidConfigVersion.cmake")
+ set(_filename_diffvoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}DiffVoidConfigVersion.cmake")
+
+ set(_expected_compatible ${_expected_compatible_${_compat}})
+
+ # Test "normal" version
+ set(_expected_unsuitable 0)
+ message(STATUS "TEST write_basic_config_version_file(VERSION ${_version_installed} \
+COMPATIBILITY ${_compat}) vs. ${_version_requested} \
+(expected compatible = ${_expected_compatible}, unsuitable = ${_expected_unsuitable})")
+ test_write_basic_config_version_file_check("${_filename}")
+
+ # test empty CMAKE_SIZEOF_VOID_P version:
+ set(_expected_unsuitable 0)
+ message(STATUS "TEST write_basic_config_version_file(VERSION ${_version_installed} \
+COMPATIBILITY ${_compat}) vs. ${_version_requested} (no CMAKE_SIZEOF_VOID_P) \
+(expected compatible = ${_expected_compatible}, unsuitable = ${_expected_unsuitable})")
+ test_write_basic_config_version_file_check("${_filename_novoid}")
+
+ # test different CMAKE_SIZEOF_VOID_P version:
+ set(_expected_unsuitable 1)
+ message(STATUS "TEST write_basic_config_version_file(VERSION ${_version_installed} \
+COMPATIBILITY ${_compat}) vs. ${_version_requested} (different CMAKE_SIZEOF_VOID_P) \
+(expected compatible = ${_expected_compatible}, unsuitable = ${_expected_unsuitable})")
+ test_write_basic_config_version_file_check("${_filename_diffvoid}")
+
+ endforeach()
+endfunction()
+
+
+test_write_basic_config_version_file_prepare(4)
+test_write_basic_config_version_file_prepare(4.05)
+test_write_basic_config_version_file_prepare(4.5.06)
+test_write_basic_config_version_file_prepare(4.05.06.007)
+
+# AnyNewerVersion
+# | SameMajorVersion
+# | | SameMinorVersion
+# | | | ExactVersion
+# | | | |
+test_write_basic_config_version_file(4.05 0 1 0 0 0) # Request 0
+test_write_basic_config_version_file(4.05 2 1 0 0 0) # Request [older major]
+test_write_basic_config_version_file(4.05 4 1 1 0 0) # Request [same major]
+test_write_basic_config_version_file(4.05 9 0 0 0 0) # Request [newer major]
+
+test_write_basic_config_version_file(4.05 0.0 1 0 0 0) # Request 0.0
+test_write_basic_config_version_file(4.05 0.2 1 0 0 0) # Request 0.[older minor]
+test_write_basic_config_version_file(4.05 0.5 1 0 0 0) # Request 0.[same minor]
+test_write_basic_config_version_file(4.05 0.9 1 0 0 0) # Request 0.[newer minor]
+test_write_basic_config_version_file(4.05 2.0 1 0 0 0) # Request [older major].0
+test_write_basic_config_version_file(4.05 2.2 1 0 0 0) # Request [older major].[older minor]
+test_write_basic_config_version_file(4.05 2.5 1 0 0 0) # Request [older major].[same minor]
+test_write_basic_config_version_file(4.05 2.9 1 0 0 0) # Request [older major].[newer minor]
+test_write_basic_config_version_file(4.05 4.0 1 1 0 0) # Request [same major].0
+test_write_basic_config_version_file(4.05 4.2 1 1 0 0) # Request [same major].[older minor]
+test_write_basic_config_version_file(4.05 4.05 1 1 1 1) # Request [same major].[same minor]
+test_write_basic_config_version_file(4.05 4.9 0 0 0 0) # Request [same major].[newer minor]
+test_write_basic_config_version_file(4.05 9.0 0 0 0 0) # Request [newer major].0
+test_write_basic_config_version_file(4.05 9.1 0 0 0 0) # Request [newer major].[older minor]
+test_write_basic_config_version_file(4.05 9.5 0 0 0 0) # Request [newer major].[same minor]
+test_write_basic_config_version_file(4.05 9.9 0 0 0 0) # Request [newer major].[newer minor]
+
+test_write_basic_config_version_file(4.05 0.0.0 1 0 0 0) # Request 0.0.0
+test_write_basic_config_version_file(4.05 0.0.9 1 0 0 0) # Request 0.0.[newer patch]
+test_write_basic_config_version_file(4.05 0.2.0 1 0 0 0) # Request 0.[older minor].0
+test_write_basic_config_version_file(4.05 0.2.9 1 0 0 0) # Request 0.[older minor].[newer patch]
+test_write_basic_config_version_file(4.05 0.5.0 1 0 0 0) # Request 0.[same minor].0
+test_write_basic_config_version_file(4.05 0.5.9 1 0 0 0) # Request 0.[same minor].[newer patch]
+test_write_basic_config_version_file(4.05 0.9.0 1 0 0 0) # Request 0.[newer minor].0
+test_write_basic_config_version_file(4.05 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch]
+test_write_basic_config_version_file(4.05 2.0.0 1 0 0 0) # Request [older major].0.0
+test_write_basic_config_version_file(4.05 2.0.9 1 0 0 0) # Request [older major].0.[newer patch]
+test_write_basic_config_version_file(4.05 2.2.0 1 0 0 0) # Request [older major].[older minor].0
+test_write_basic_config_version_file(4.05 2.2.9 1 0 0 0) # Request [older major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.05 2.5.0 1 0 0 0) # Request [older major].[same minor].0
+test_write_basic_config_version_file(4.05 2.5.9 1 0 0 0) # Request [older major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.05 2.9.0 1 0 0 0) # Request [older major].[newer minor].0
+test_write_basic_config_version_file(4.05 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.05 4.0.0 1 1 0 0) # Request [same major].0.0
+test_write_basic_config_version_file(4.05 4.0.9 1 1 0 0) # Request [same major].0.[newer patch]
+test_write_basic_config_version_file(4.05 4.2.0 1 1 0 0) # Request [same major].[older minor].0
+test_write_basic_config_version_file(4.05 4.2.9 1 1 0 0) # Request [same major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.05 4.05.0 1 1 1 0) # Request [same major].[same minor].0
+test_write_basic_config_version_file(4.05 4.5.9 0 0 0 0) # Request [same major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.05 4.9.0 0 0 0 0) # Request [same major].[newer minor].0
+test_write_basic_config_version_file(4.05 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.05 9.0.0 0 0 0 0) # Request [newer major].0.0
+test_write_basic_config_version_file(4.05 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch]
+test_write_basic_config_version_file(4.05 9.2.0 0 0 0 0) # Request [newer major].[older minor].0
+test_write_basic_config_version_file(4.05 9.2.9 0 0 0 0) # Request [newer major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.05 9.5.0 0 0 0 0) # Request [newer major].[same minor].0
+test_write_basic_config_version_file(4.05 9.5.9 0 0 0 0) # Request [newer major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.05 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0
+test_write_basic_config_version_file(4.05 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch]
+
+test_write_basic_config_version_file(4.05 0.0.0.0 1 0 0 0) # Request 0.0.0.0
+test_write_basic_config_version_file(4.05 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak]
+test_write_basic_config_version_file(4.05 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0
+test_write_basic_config_version_file(4.05 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 0.2.0.0 1 0 0 0) # Request 0.[older minor].0.0
+test_write_basic_config_version_file(4.05 0.2.0.9 1 0 0 0) # Request 0.[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 0.2.9.0 1 0 0 0) # Request 0.[older minor].[newer patch].0
+test_write_basic_config_version_file(4.05 0.2.9.9 1 0 0 0) # Request 0.[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 0.5.0.0 1 0 0 0) # Request 0.[same minor].0.0
+test_write_basic_config_version_file(4.05 0.5.0.9 1 0 0 0) # Request 0.[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 0.5.9.0 1 0 0 0) # Request 0.[same minor].[newer patch].0
+test_write_basic_config_version_file(4.05 0.5.9.9 1 0 0 0) # Request 0.[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0
+test_write_basic_config_version_file(4.05 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.05 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 2.0.0.0 1 0 0 0) # Request [older major].0.0.0
+test_write_basic_config_version_file(4.05 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.05 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0
+test_write_basic_config_version_file(4.05 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 2.2.0.0 1 0 0 0) # Request [older major].[older minor].0.0
+test_write_basic_config_version_file(4.05 2.2.0.9 1 0 0 0) # Request [older major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 2.2.9.0 1 0 0 0) # Request [older major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.05 2.2.9.9 1 0 0 0) # Request [older major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 2.5.0.0 1 0 0 0) # Request [older major].[same minor].0.0
+test_write_basic_config_version_file(4.05 2.5.0.9 1 0 0 0) # Request [older major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 2.5.9.0 1 0 0 0) # Request [older major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.05 2.5.9.9 1 0 0 0) # Request [older major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0
+test_write_basic_config_version_file(4.05 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.05 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 4.0.0.0 1 1 0 0) # Request [same major].0.0.0
+test_write_basic_config_version_file(4.05 4.0.0.9 1 1 0 0) # Request [same major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.05 4.0.9.0 1 1 0 0) # Request [same major].0.[newer patch].0
+test_write_basic_config_version_file(4.05 4.0.9.9 1 1 0 0) # Request [same major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 4.2.0.0 1 1 0 0) # Request [same major].[older minor].0.0
+test_write_basic_config_version_file(4.05 4.2.0.9 1 1 0 0) # Request [same major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 4.2.9.0 1 1 0 0) # Request [same major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.05 4.2.9.9 1 1 0 0) # Request [same major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 4.5.0.0 1 1 1 0) # Request [same major].[same minor].0.0
+test_write_basic_config_version_file(4.05 4.5.0.9 0 0 0 0) # Request [same major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 4.5.9.0 0 0 0 0) # Request [same major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.05 4.5.9.9 0 0 0 0) # Request [same major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0
+test_write_basic_config_version_file(4.05 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.05 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0
+test_write_basic_config_version_file(4.05 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.05 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0
+test_write_basic_config_version_file(4.05 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 9.2.0.0 0 0 0 0) # Request [newer major].[older minor].0.0
+test_write_basic_config_version_file(4.05 9.2.0.9 0 0 0 0) # Request [newer major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 9.2.9.0 0 0 0 0) # Request [newer major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.05 9.2.9.9 0 0 0 0) # Request [newer major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 9.5.0.0 0 0 0 0) # Request [newer major].[same minor].0.0
+test_write_basic_config_version_file(4.05 9.5.0.9 0 0 0 0) # Request [newer major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 9.5.9.0 0 0 0 0) # Request [newer major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.05 9.5.9.9 0 0 0 0) # Request [newer major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0
+test_write_basic_config_version_file(4.05 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.05 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak]
+
+
+test_write_basic_config_version_file(4.5.06 0 1 0 0 0) # Request 0
+test_write_basic_config_version_file(4.5.06 2 1 0 0 0) # Request [older major]
+test_write_basic_config_version_file(4.5.06 4 1 1 0 0) # Request [same major]
+test_write_basic_config_version_file(4.5.06 9 0 0 0 0) # Request [newer major]
+
+test_write_basic_config_version_file(4.5.06 0.0 1 0 0 0) # Request 0.0
+test_write_basic_config_version_file(4.5.06 0.2 1 0 0 0) # Request 0.[older minor]
+test_write_basic_config_version_file(4.5.06 0.5 1 0 0 0) # Request 0.[same minor]
+test_write_basic_config_version_file(4.5.06 0.9 1 0 0 0) # Request 0.[newer minor]
+test_write_basic_config_version_file(4.5.06 2.0 1 0 0 0) # Request [older major].0
+test_write_basic_config_version_file(4.5.06 2.2 1 0 0 0) # Request [older major].[older minor]
+test_write_basic_config_version_file(4.5.06 2.5 1 0 0 0) # Request [older major].[same minor]
+test_write_basic_config_version_file(4.5.06 2.9 1 0 0 0) # Request [older major].[newer minor]
+test_write_basic_config_version_file(4.5.06 4.0 1 1 0 0) # Request [same major].0
+test_write_basic_config_version_file(4.5.06 4.2 1 1 0 0) # Request [same major].[older minor]
+test_write_basic_config_version_file(4.5.06 4.5 1 1 1 0) # Request [same major].[same minor]
+test_write_basic_config_version_file(4.5.06 4.9 0 0 0 0) # Request [same major].[newer minor]
+test_write_basic_config_version_file(4.5.06 9.0 0 0 0 0) # Request [newer major].0
+test_write_basic_config_version_file(4.5.06 9.1 0 0 0 0) # Request [newer major].[older minor]
+test_write_basic_config_version_file(4.5.06 9.5 0 0 0 0) # Request [newer major].[same minor]
+test_write_basic_config_version_file(4.5.06 9.9 0 0 0 0) # Request [newer major].[newer minor]
+
+test_write_basic_config_version_file(4.5.06 0.0.0 1 0 0 0) # Request 0.0.0
+test_write_basic_config_version_file(4.5.06 0.0.2 1 0 0 0) # Request 0.0.[older patch]
+test_write_basic_config_version_file(4.5.06 0.0.6 1 0 0 0) # Request 0.0.[same patch]
+test_write_basic_config_version_file(4.5.06 0.0.9 1 0 0 0) # Request 0.0.[newer patch]
+test_write_basic_config_version_file(4.5.06 0.2.0 1 0 0 0) # Request 0.[older minor].0
+test_write_basic_config_version_file(4.5.06 0.2.2 1 0 0 0) # Request 0.[older minor].[older patch]
+test_write_basic_config_version_file(4.5.06 0.2.6 1 0 0 0) # Request 0.[older minor].[same patch]
+test_write_basic_config_version_file(4.5.06 0.2.9 1 0 0 0) # Request 0.[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 0.5.0 1 0 0 0) # Request 0.[same minor].0
+test_write_basic_config_version_file(4.5.06 0.5.2 1 0 0 0) # Request 0.[same minor].[older patch]
+test_write_basic_config_version_file(4.5.06 0.5.6 1 0 0 0) # Request 0.[same minor].[same patch]
+test_write_basic_config_version_file(4.5.06 0.5.9 1 0 0 0) # Request 0.[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 0.9.0 1 0 0 0) # Request 0.[newer minor].0
+test_write_basic_config_version_file(4.5.06 0.9.2 1 0 0 0) # Request 0.[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.06 0.9.6 1 0 0 0) # Request 0.[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.06 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 2.0.0 1 0 0 0) # Request [older major].0.0
+test_write_basic_config_version_file(4.5.06 2.0.2 1 0 0 0) # Request [older major].0.[older patch]
+test_write_basic_config_version_file(4.5.06 2.0.6 1 0 0 0) # Request [older major].0.[same patch]
+test_write_basic_config_version_file(4.5.06 2.0.9 1 0 0 0) # Request [older major].0.[newer patch]
+test_write_basic_config_version_file(4.5.06 2.2.0 1 0 0 0) # Request [older major].[older minor].0
+test_write_basic_config_version_file(4.5.06 2.2.2 1 0 0 0) # Request [older major].[older minor].[older patch]
+test_write_basic_config_version_file(4.5.06 2.2.6 1 0 0 0) # Request [older major].[older minor].[same patch]
+test_write_basic_config_version_file(4.5.06 2.2.9 1 0 0 0) # Request [older major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 2.5.0 1 0 0 0) # Request [older major].[same minor].0
+test_write_basic_config_version_file(4.5.06 2.5.2 1 0 0 0) # Request [older major].[same minor].[older patch]
+test_write_basic_config_version_file(4.5.06 2.5.6 1 0 0 0) # Request [older major].[same minor].[same patch]
+test_write_basic_config_version_file(4.5.06 2.5.9 1 0 0 0) # Request [older major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 2.9.0 1 0 0 0) # Request [older major].[newer minor].0
+test_write_basic_config_version_file(4.5.06 2.9.2 1 0 0 0) # Request [older major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.06 2.9.6 1 0 0 0) # Request [older major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.06 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 4.0.0 1 1 0 0) # Request [same major].0.0
+test_write_basic_config_version_file(4.5.06 4.0.2 1 1 0 0) # Request [same major].0.[older patch]
+test_write_basic_config_version_file(4.5.06 4.0.6 1 1 0 0) # Request [same major].0.[same patch]
+test_write_basic_config_version_file(4.5.06 4.0.9 1 1 0 0) # Request [same major].0.[newer patch]
+test_write_basic_config_version_file(4.5.06 4.2.0 1 1 0 0) # Request [same major].[older minor].0
+test_write_basic_config_version_file(4.5.06 4.2.2 1 1 0 0) # Request [same major].[older minor].[older patch]
+test_write_basic_config_version_file(4.5.06 4.2.6 1 1 0 0) # Request [same major].[older minor].[same patch]
+test_write_basic_config_version_file(4.5.06 4.2.9 1 1 0 0) # Request [same major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 4.5.0 1 1 1 0) # Request [same major].[same minor].0
+test_write_basic_config_version_file(4.5.06 4.5.2 1 1 1 0) # Request [same major].[same minor].[older patch]
+test_write_basic_config_version_file(4.5.06 4.5.06 1 1 1 1) # Request [same major].[same minor].[same patch]
+test_write_basic_config_version_file(4.5.06 4.5.9 0 0 0 0) # Request [same major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 4.9.0 0 0 0 0) # Request [same major].[newer minor].0
+test_write_basic_config_version_file(4.5.06 4.9.2 0 0 0 0) # Request [same major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.06 4.9.6 0 0 0 0) # Request [same major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.06 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 9.0.0 0 0 0 0) # Request [newer major].0.0
+test_write_basic_config_version_file(4.5.06 9.0.2 0 0 0 0) # Request [newer major].0.[older patch]
+test_write_basic_config_version_file(4.5.06 9.0.6 0 0 0 0) # Request [newer major].0.[same patch]
+test_write_basic_config_version_file(4.5.06 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch]
+test_write_basic_config_version_file(4.5.06 9.2.0 0 0 0 0) # Request [newer major].[older minor].0
+test_write_basic_config_version_file(4.5.06 9.2.2 0 0 0 0) # Request [newer major].[older minor].[older patch]
+test_write_basic_config_version_file(4.5.06 9.2.6 0 0 0 0) # Request [newer major].[older minor].[same patch]
+test_write_basic_config_version_file(4.5.06 9.2.9 0 0 0 0) # Request [newer major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 9.5.0 0 0 0 0) # Request [newer major].[same minor].0
+test_write_basic_config_version_file(4.5.06 9.5.2 0 0 0 0) # Request [newer major].[same minor].[older patch]
+test_write_basic_config_version_file(4.5.06 9.5.6 0 0 0 0) # Request [newer major].[same minor].[same patch]
+test_write_basic_config_version_file(4.5.06 9.5.9 0 0 0 0) # Request [newer major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.06 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0
+test_write_basic_config_version_file(4.5.06 9.9.2 0 0 0 0) # Request [newer major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.06 9.9.6 0 0 0 0) # Request [newer major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.06 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch]
+
+test_write_basic_config_version_file(4.5.06 0.0.0.0 1 0 0 0) # Request 0.0.0.0
+test_write_basic_config_version_file(4.5.06 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.0.2.0 1 0 0 0) # Request 0.0.[older patch].0
+test_write_basic_config_version_file(4.5.06 0.0.2.9 1 0 0 0) # Request 0.0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.0.6.0 1 0 0 0) # Request 0.0.[same patch].0
+test_write_basic_config_version_file(4.5.06 0.0.6.9 1 0 0 0) # Request 0.0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0
+test_write_basic_config_version_file(4.5.06 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.2.0.0 1 0 0 0) # Request 0.[older minor].0.0
+test_write_basic_config_version_file(4.5.06 0.2.0.9 1 0 0 0) # Request 0.[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.2.2.0 1 0 0 0) # Request 0.[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 0.2.2.9 1 0 0 0) # Request 0.[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.2.6.0 1 0 0 0) # Request 0.[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 0.2.6.9 1 0 0 0) # Request 0.[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.2.9.0 1 0 0 0) # Request 0.[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 0.2.9.9 1 0 0 0) # Request 0.[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.5.0.0 1 0 0 0) # Request 0.[same minor].0.0
+test_write_basic_config_version_file(4.5.06 0.5.0.9 1 0 0 0) # Request 0.[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.5.2.0 1 0 0 0) # Request 0.[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 0.5.2.9 1 0 0 0) # Request 0.[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.5.6.0 1 0 0 0) # Request 0.[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 0.5.6.9 1 0 0 0) # Request 0.[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.5.9.0 1 0 0 0) # Request 0.[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 0.5.9.9 1 0 0 0) # Request 0.[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0
+test_write_basic_config_version_file(4.5.06 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.9.2.0 1 0 0 0) # Request 0.[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 0.9.2.9 1 0 0 0) # Request 0.[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.9.6.0 1 0 0 0) # Request 0.[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 0.9.6.9 1 0 0 0) # Request 0.[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.0.0.0 1 0 0 0) # Request [older major].0.0.0
+test_write_basic_config_version_file(4.5.06 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.0.2.0 1 0 0 0) # Request [older major].0.[older patch].0
+test_write_basic_config_version_file(4.5.06 2.0.2.9 1 0 0 0) # Request [older major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.0.6.0 1 0 0 0) # Request [older major].0.[same patch].0
+test_write_basic_config_version_file(4.5.06 2.0.6.9 1 0 0 0) # Request [older major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0
+test_write_basic_config_version_file(4.5.06 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.2.0.0 1 0 0 0) # Request [older major].[older minor].0.0
+test_write_basic_config_version_file(4.5.06 2.2.0.9 1 0 0 0) # Request [older major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.2.2.0 1 0 0 0) # Request [older major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 2.2.2.9 1 0 0 0) # Request [older major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.2.6.0 1 0 0 0) # Request [older major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 2.2.6.9 1 0 0 0) # Request [older major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.2.9.0 1 0 0 0) # Request [older major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 2.2.9.9 1 0 0 0) # Request [older major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.5.0.0 1 0 0 0) # Request [older major].[same minor].0.0
+test_write_basic_config_version_file(4.5.06 2.5.0.9 1 0 0 0) # Request [older major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.5.2.0 1 0 0 0) # Request [older major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 2.5.2.9 1 0 0 0) # Request [older major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.5.6.0 1 0 0 0) # Request [older major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 2.5.6.9 1 0 0 0) # Request [older major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.5.9.0 1 0 0 0) # Request [older major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 2.5.9.9 1 0 0 0) # Request [older major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0
+test_write_basic_config_version_file(4.5.06 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.9.2.0 1 0 0 0) # Request [older major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 2.9.2.9 1 0 0 0) # Request [older major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.9.6.0 1 0 0 0) # Request [older major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 2.9.6.9 1 0 0 0) # Request [older major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.0.0.0 1 1 0 0) # Request [same major].0.0.0
+test_write_basic_config_version_file(4.5.06 4.0.0.9 1 1 0 0) # Request [same major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.0.2.0 1 1 0 0) # Request [same major].0.[older patch].0
+test_write_basic_config_version_file(4.5.06 4.0.2.9 1 1 0 0) # Request [same major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.0.6.0 1 1 0 0) # Request [same major].0.[same patch].0
+test_write_basic_config_version_file(4.5.06 4.0.6.9 1 1 0 0) # Request [same major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.0.9.0 1 1 0 0) # Request [same major].0.[newer patch].0
+test_write_basic_config_version_file(4.5.06 4.0.9.9 1 1 0 0) # Request [same major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.2.0.0 1 1 0 0) # Request [same major].[older minor].0.0
+test_write_basic_config_version_file(4.5.06 4.2.0.9 1 1 0 0) # Request [same major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.2.2.0 1 1 0 0) # Request [same major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 4.2.2.9 1 1 0 0) # Request [same major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.2.6.0 1 1 0 0) # Request [same major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 4.2.6.9 1 1 0 0) # Request [same major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.2.9.0 1 1 0 0) # Request [same major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 4.2.9.9 1 1 0 0) # Request [same major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.5.0.0 1 1 1 0) # Request [same major].[same minor].0.0
+test_write_basic_config_version_file(4.5.06 4.5.0.9 1 1 1 0) # Request [same major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.5.2.0 1 1 1 0) # Request [same major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 4.5.2.9 1 1 1 0) # Request [same major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.5.06.0 1 1 1 1) # Request [same major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 4.5.06.9 0 0 0 1) # Request [same major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.5.9.0 0 0 0 0) # Request [same major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 4.5.9.9 0 0 0 0) # Request [same major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0
+test_write_basic_config_version_file(4.5.06 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.9.2.0 0 0 0 0) # Request [same major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 4.9.2.9 0 0 0 0) # Request [same major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.9.6.0 0 0 0 0) # Request [same major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 4.9.6.9 0 0 0 0) # Request [same major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0
+test_write_basic_config_version_file(4.5.06 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.0.2.0 0 0 0 0) # Request [newer major].0.[older patch].0
+test_write_basic_config_version_file(4.5.06 9.0.2.9 0 0 0 0) # Request [newer major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.0.6.0 0 0 0 0) # Request [newer major].0.[same patch].0
+test_write_basic_config_version_file(4.5.06 9.0.6.9 0 0 0 0) # Request [newer major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0
+test_write_basic_config_version_file(4.5.06 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.2.0.0 0 0 0 0) # Request [newer major].[older minor].0.0
+test_write_basic_config_version_file(4.5.06 9.2.0.9 0 0 0 0) # Request [newer major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.2.2.0 0 0 0 0) # Request [newer major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 9.2.2.9 0 0 0 0) # Request [newer major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.2.6.0 0 0 0 0) # Request [newer major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 9.2.6.9 0 0 0 0) # Request [newer major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.2.9.0 0 0 0 0) # Request [newer major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 9.2.9.9 0 0 0 0) # Request [newer major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.5.0.0 0 0 0 0) # Request [newer major].[same minor].0.0
+test_write_basic_config_version_file(4.5.06 9.5.0.9 0 0 0 0) # Request [newer major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.5.2.0 0 0 0 0) # Request [newer major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 9.5.2.9 0 0 0 0) # Request [newer major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.5.6.0 0 0 0 0) # Request [newer major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 9.5.6.9 0 0 0 0) # Request [newer major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.5.9.0 0 0 0 0) # Request [newer major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 9.5.9.9 0 0 0 0) # Request [newer major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0
+test_write_basic_config_version_file(4.5.06 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.9.2.0 0 0 0 0) # Request [newer major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.06 9.9.2.9 0 0 0 0) # Request [newer major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.9.6.0 0 0 0 0) # Request [newer major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.06 9.9.6.9 0 0 0 0) # Request [newer major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.06 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.06 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak]
+
+
+test_write_basic_config_version_file(4.05.06.007 0 1 0 0 0) # Request 0
+test_write_basic_config_version_file(4.05.06.007 2 1 0 0 0) # Request [older major]
+test_write_basic_config_version_file(4.05.06.007 4 1 1 0 0) # Request [same major]
+test_write_basic_config_version_file(4.05.06.007 9 0 0 0 0) # Request [newer major]
+
+test_write_basic_config_version_file(4.05.06.007 0.0 1 0 0 0) # Request 0.0
+test_write_basic_config_version_file(4.05.06.007 0.2 1 0 0 0) # Request 0.[older minor]
+test_write_basic_config_version_file(4.05.06.007 0.5 1 0 0 0) # Request 0.[same minor]
+test_write_basic_config_version_file(4.05.06.007 0.9 1 0 0 0) # Request 0.[newer minor]
+test_write_basic_config_version_file(4.05.06.007 2.0 1 0 0 0) # Request [older major].0
+test_write_basic_config_version_file(4.05.06.007 2.2 1 0 0 0) # Request [older major].[older minor]
+test_write_basic_config_version_file(4.05.06.007 2.5 1 0 0 0) # Request [older major].[same minor]
+test_write_basic_config_version_file(4.05.06.007 2.9 1 0 0 0) # Request [older major].[newer minor]
+test_write_basic_config_version_file(4.05.06.007 4.0 1 1 0 0) # Request [same major].0
+test_write_basic_config_version_file(4.05.06.007 4.2 1 1 0 0) # Request [same major].[older minor]
+test_write_basic_config_version_file(4.05.06.007 4.5 1 1 1 0) # Request [same major].[same minor]
+test_write_basic_config_version_file(4.05.06.007 4.9 0 0 0 0) # Request [same major].[newer minor]
+test_write_basic_config_version_file(4.05.06.007 9.0 0 0 0 0) # Request [newer major].0
+test_write_basic_config_version_file(4.05.06.007 9.1 0 0 0 0) # Request [newer major].[older minor]
+test_write_basic_config_version_file(4.05.06.007 9.5 0 0 0 0) # Request [newer major].[same minor]
+test_write_basic_config_version_file(4.05.06.007 9.9 0 0 0 0) # Request [newer major].[newer minor]
+
+test_write_basic_config_version_file(4.05.06.007 0.0.0 1 0 0 0) # Request 0.0.0
+test_write_basic_config_version_file(4.05.06.007 0.0.2 1 0 0 0) # Request 0.0.[older patch]
+test_write_basic_config_version_file(4.05.06.007 0.0.6 1 0 0 0) # Request 0.0.[same patch]
+test_write_basic_config_version_file(4.05.06.007 0.0.9 1 0 0 0) # Request 0.0.[newer patch]
+test_write_basic_config_version_file(4.05.06.007 0.2.0 1 0 0 0) # Request 0.[older minor].0
+test_write_basic_config_version_file(4.05.06.007 0.2.2 1 0 0 0) # Request 0.[older minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 0.2.6 1 0 0 0) # Request 0.[older minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 0.2.9 1 0 0 0) # Request 0.[older minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 0.5.0 1 0 0 0) # Request 0.[same minor].0
+test_write_basic_config_version_file(4.05.06.007 0.5.2 1 0 0 0) # Request 0.[same minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 0.5.6 1 0 0 0) # Request 0.[same minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 0.5.9 1 0 0 0) # Request 0.[same minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 0.9.0 1 0 0 0) # Request 0.[newer minor].0
+test_write_basic_config_version_file(4.05.06.007 0.9.2 1 0 0 0) # Request 0.[newer minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 0.9.6 1 0 0 0) # Request 0.[newer minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 2.0.0 1 0 0 0) # Request [older major].0.0
+test_write_basic_config_version_file(4.05.06.007 2.0.2 1 0 0 0) # Request [older major].0.[older patch]
+test_write_basic_config_version_file(4.05.06.007 2.0.6 1 0 0 0) # Request [older major].0.[same patch]
+test_write_basic_config_version_file(4.05.06.007 2.0.9 1 0 0 0) # Request [older major].0.[newer patch]
+test_write_basic_config_version_file(4.05.06.007 2.2.0 1 0 0 0) # Request [older major].[older minor].0
+test_write_basic_config_version_file(4.05.06.007 2.2.2 1 0 0 0) # Request [older major].[older minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 2.2.6 1 0 0 0) # Request [older major].[older minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 2.2.9 1 0 0 0) # Request [older major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 2.5.0 1 0 0 0) # Request [older major].[same minor].0
+test_write_basic_config_version_file(4.05.06.007 2.5.2 1 0 0 0) # Request [older major].[same minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 2.5.6 1 0 0 0) # Request [older major].[same minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 2.5.9 1 0 0 0) # Request [older major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 2.9.0 1 0 0 0) # Request [older major].[newer minor].0
+test_write_basic_config_version_file(4.05.06.007 2.9.2 1 0 0 0) # Request [older major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 2.9.6 1 0 0 0) # Request [older major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 4.0.0 1 1 0 0) # Request [same major].0.0
+test_write_basic_config_version_file(4.05.06.007 4.0.2 1 1 0 0) # Request [same major].0.[older patch]
+test_write_basic_config_version_file(4.05.06.007 4.0.6 1 1 0 0) # Request [same major].0.[same patch]
+test_write_basic_config_version_file(4.05.06.007 4.0.9 1 1 0 0) # Request [same major].0.[newer patch]
+test_write_basic_config_version_file(4.05.06.007 4.2.0 1 1 0 0) # Request [same major].[older minor].0
+test_write_basic_config_version_file(4.05.06.007 4.2.2 1 1 0 0) # Request [same major].[older minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 4.2.6 1 1 0 0) # Request [same major].[older minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 4.2.9 1 1 0 0) # Request [same major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 4.5.0 1 1 1 0) # Request [same major].[same minor].0
+test_write_basic_config_version_file(4.05.06.007 4.5.2 1 1 1 0) # Request [same major].[same minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 4.05.06 1 1 1 1) # Request [same major].[same minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 4.5.9 0 0 0 0) # Request [same major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 4.9.0 0 0 0 0) # Request [same major].[newer minor].0
+test_write_basic_config_version_file(4.05.06.007 4.9.2 0 0 0 0) # Request [same major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 4.9.6 0 0 0 0) # Request [same major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 9.0.0 0 0 0 0) # Request [newer major].0.0
+test_write_basic_config_version_file(4.05.06.007 9.0.2 0 0 0 0) # Request [newer major].0.[older patch]
+test_write_basic_config_version_file(4.05.06.007 9.0.6 0 0 0 0) # Request [newer major].0.[same patch]
+test_write_basic_config_version_file(4.05.06.007 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch]
+test_write_basic_config_version_file(4.05.06.007 9.2.0 0 0 0 0) # Request [newer major].[older minor].0
+test_write_basic_config_version_file(4.05.06.007 9.2.2 0 0 0 0) # Request [newer major].[older minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 9.2.6 0 0 0 0) # Request [newer major].[older minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 9.2.9 0 0 0 0) # Request [newer major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 9.5.0 0 0 0 0) # Request [newer major].[same minor].0
+test_write_basic_config_version_file(4.05.06.007 9.5.2 0 0 0 0) # Request [newer major].[same minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 9.5.6 0 0 0 0) # Request [newer major].[same minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 9.5.9 0 0 0 0) # Request [newer major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.05.06.007 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0
+test_write_basic_config_version_file(4.05.06.007 9.9.2 0 0 0 0) # Request [newer major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.05.06.007 9.9.6 0 0 0 0) # Request [newer major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.05.06.007 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch]
+
+test_write_basic_config_version_file(4.05.06.007 0.0.0.0 1 0 0 0) # Request 0.0.0.0
+test_write_basic_config_version_file(4.05.06.007 0.0.0.2 1 0 0 0) # Request 0.0.0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.0.7 1 0 0 0) # Request 0.0.0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.2.0 1 0 0 0) # Request 0.0.[older patch].0
+test_write_basic_config_version_file(4.05.06.007 0.0.2.2 1 0 0 0) # Request 0.0.[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.2.7 1 0 0 0) # Request 0.0.[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.2.9 1 0 0 0) # Request 0.0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.6.0 1 0 0 0) # Request 0.0.[same patch].0
+test_write_basic_config_version_file(4.05.06.007 0.0.6.2 1 0 0 0) # Request 0.0.[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.6.7 1 0 0 0) # Request 0.0.[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.6.9 1 0 0 0) # Request 0.0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 0.0.9.2 1 0 0 0) # Request 0.0.[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.9.7 1 0 0 0) # Request 0.0.[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.0.0 1 0 0 0) # Request 0.[older minor].0.0
+test_write_basic_config_version_file(4.05.06.007 0.2.0.2 1 0 0 0) # Request 0.[older minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.0.7 1 0 0 0) # Request 0.[older minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.0.9 1 0 0 0) # Request 0.[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.2.0 1 0 0 0) # Request 0.[older minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 0.2.2.2 1 0 0 0) # Request 0.[older minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.2.7 1 0 0 0) # Request 0.[older minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.2.9 1 0 0 0) # Request 0.[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.6.0 1 0 0 0) # Request 0.[older minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 0.2.6.2 1 0 0 0) # Request 0.[older minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.6.7 1 0 0 0) # Request 0.[older minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.6.9 1 0 0 0) # Request 0.[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.9.0 1 0 0 0) # Request 0.[older minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 0.2.9.2 1 0 0 0) # Request 0.[older minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.9.7 1 0 0 0) # Request 0.[older minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.2.9.9 1 0 0 0) # Request 0.[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.0.0 1 0 0 0) # Request 0.[same minor].0.0
+test_write_basic_config_version_file(4.05.06.007 0.5.0.2 1 0 0 0) # Request 0.[same minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.0.7 1 0 0 0) # Request 0.[same minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.0.9 1 0 0 0) # Request 0.[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.2.0 1 0 0 0) # Request 0.[same minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 0.5.2.2 1 0 0 0) # Request 0.[same minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.2.7 1 0 0 0) # Request 0.[same minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.2.9 1 0 0 0) # Request 0.[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.6.0 1 0 0 0) # Request 0.[same minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 0.5.6.2 1 0 0 0) # Request 0.[same minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.6.7 1 0 0 0) # Request 0.[same minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.6.9 1 0 0 0) # Request 0.[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.9.0 1 0 0 0) # Request 0.[same minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 0.5.9.2 1 0 0 0) # Request 0.[same minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.9.7 1 0 0 0) # Request 0.[same minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.5.9.9 1 0 0 0) # Request 0.[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0
+test_write_basic_config_version_file(4.05.06.007 0.9.0.2 1 0 0 0) # Request 0.[newer minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.0.7 1 0 0 0) # Request 0.[newer minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.2.0 1 0 0 0) # Request 0.[newer minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 0.9.2.2 1 0 0 0) # Request 0.[newer minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.2.7 1 0 0 0) # Request 0.[newer minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.2.9 1 0 0 0) # Request 0.[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.6.0 1 0 0 0) # Request 0.[newer minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 0.9.6.2 1 0 0 0) # Request 0.[newer minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.6.7 1 0 0 0) # Request 0.[newer minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.6.9 1 0 0 0) # Request 0.[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 0.9.9.2 1 0 0 0) # Request 0.[newer minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.9.7 1 0 0 0) # Request 0.[newer minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.0.0 1 0 0 0) # Request [older major].0.0.0
+test_write_basic_config_version_file(4.05.06.007 2.0.0.2 1 0 0 0) # Request [older major].0.0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.0.7 1 0 0 0) # Request [older major].0.0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.2.0 1 0 0 0) # Request [older major].0.[older patch].0
+test_write_basic_config_version_file(4.05.06.007 2.0.2.2 1 0 0 0) # Request [older major].0.[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.2.7 1 0 0 0) # Request [older major].0.[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.2.9 1 0 0 0) # Request [older major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.6.0 1 0 0 0) # Request [older major].0.[same patch].0
+test_write_basic_config_version_file(4.05.06.007 2.0.6.2 1 0 0 0) # Request [older major].0.[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.6.7 1 0 0 0) # Request [older major].0.[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.6.9 1 0 0 0) # Request [older major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 2.0.9.2 1 0 0 0) # Request [older major].0.[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.9.7 1 0 0 0) # Request [older major].0.[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.0.0 1 0 0 0) # Request [older major].[older minor].0.0
+test_write_basic_config_version_file(4.05.06.007 2.2.0.2 1 0 0 0) # Request [older major].[older minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.0.7 1 0 0 0) # Request [older major].[older minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.0.9 1 0 0 0) # Request [older major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.2.0 1 0 0 0) # Request [older major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 2.2.2.2 1 0 0 0) # Request [older major].[older minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.2.7 1 0 0 0) # Request [older major].[older minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.2.9 1 0 0 0) # Request [older major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.6.0 1 0 0 0) # Request [older major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 2.2.6.2 1 0 0 0) # Request [older major].[older minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.6.7 1 0 0 0) # Request [older major].[older minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.6.9 1 0 0 0) # Request [older major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.9.0 1 0 0 0) # Request [older major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 2.2.9.2 1 0 0 0) # Request [older major].[older minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.9.7 1 0 0 0) # Request [older major].[older minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.2.9.9 1 0 0 0) # Request [older major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.0.0 1 0 0 0) # Request [older major].[same minor].0.0
+test_write_basic_config_version_file(4.05.06.007 2.5.0.2 1 0 0 0) # Request [older major].[same minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.0.7 1 0 0 0) # Request [older major].[same minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.0.9 1 0 0 0) # Request [older major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.2.0 1 0 0 0) # Request [older major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 2.5.2.2 1 0 0 0) # Request [older major].[same minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.2.7 1 0 0 0) # Request [older major].[same minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.2.9 1 0 0 0) # Request [older major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.6.0 1 0 0 0) # Request [older major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 2.5.6.2 1 0 0 0) # Request [older major].[same minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.6.7 1 0 0 0) # Request [older major].[same minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.6.9 1 0 0 0) # Request [older major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.9.0 1 0 0 0) # Request [older major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 2.5.9.2 1 0 0 0) # Request [older major].[same minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.9.7 1 0 0 0) # Request [older major].[same minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.5.9.9 1 0 0 0) # Request [older major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0
+test_write_basic_config_version_file(4.05.06.007 2.9.0.2 1 0 0 0) # Request [older major].[newer minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.0.7 1 0 0 0) # Request [older major].[newer minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.2.0 1 0 0 0) # Request [older major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 2.9.2.2 1 0 0 0) # Request [older major].[newer minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.2.7 1 0 0 0) # Request [older major].[newer minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.2.9 1 0 0 0) # Request [older major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.6.0 1 0 0 0) # Request [older major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 2.9.6.2 1 0 0 0) # Request [older major].[newer minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.6.7 1 0 0 0) # Request [older major].[newer minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.6.9 1 0 0 0) # Request [older major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 2.9.9.2 1 0 0 0) # Request [older major].[newer minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.9.7 1 0 0 0) # Request [older major].[newer minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.0.0 1 1 0 0) # Request [same major].0.0.0
+test_write_basic_config_version_file(4.05.06.007 4.0.0.2 1 1 0 0) # Request [same major].0.0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.0.7 1 1 0 0) # Request [same major].0.0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.0.9 1 1 0 0) # Request [same major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.2.0 1 1 0 0) # Request [same major].0.[older patch].0
+test_write_basic_config_version_file(4.05.06.007 4.0.2.2 1 1 0 0) # Request [same major].0.[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.2.7 1 1 0 0) # Request [same major].0.[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.2.9 1 1 0 0) # Request [same major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.6.0 1 1 0 0) # Request [same major].0.[same patch].0
+test_write_basic_config_version_file(4.05.06.007 4.0.6.2 1 1 0 0) # Request [same major].0.[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.6.7 1 1 0 0) # Request [same major].0.[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.6.9 1 1 0 0) # Request [same major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.9.0 1 1 0 0) # Request [same major].0.[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 4.0.9.2 1 1 0 0) # Request [same major].0.[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.9.7 1 1 0 0) # Request [same major].0.[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.0.9.9 1 1 0 0) # Request [same major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.0.0 1 1 0 0) # Request [same major].[older minor].0.0
+test_write_basic_config_version_file(4.05.06.007 4.2.0.2 1 1 0 0) # Request [same major].[older minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.0.7 1 1 0 0) # Request [same major].[older minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.0.9 1 1 0 0) # Request [same major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.2.0 1 1 0 0) # Request [same major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 4.2.2.2 1 1 0 0) # Request [same major].[older minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.2.7 1 1 0 0) # Request [same major].[older minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.2.9 1 1 0 0) # Request [same major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.6.0 1 1 0 0) # Request [same major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 4.2.6.2 1 1 0 0) # Request [same major].[older minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.6.7 1 1 0 0) # Request [same major].[older minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.6.9 1 1 0 0) # Request [same major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.9.0 1 1 0 0) # Request [same major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 4.2.9.2 1 1 0 0) # Request [same major].[older minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.9.7 1 1 0 0) # Request [same major].[older minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.2.9.9 1 1 0 0) # Request [same major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.5.0.0 1 1 1 0) # Request [same major].[same minor].0.0
+test_write_basic_config_version_file(4.05.06.007 4.5.0.2 1 1 1 0) # Request [same major].[same minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.5.0.7 1 1 1 0) # Request [same major].[same minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.5.0.9 1 1 1 0) # Request [same major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.5.2.0 1 1 1 0) # Request [same major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 4.5.2.2 1 1 1 0) # Request [same major].[same minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.5.2.7 1 1 1 0) # Request [same major].[same minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.5.2.9 1 1 1 0) # Request [same major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.05.06.007 1 1 1 1) # Request [same major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 4.05.06.2 1 1 1 1) # Request [same major].[same minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.05.06.7 1 1 1 1) # Request [same major].[same minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.05.06.9 0 0 0 1) # Request [same major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.5.9.0 0 0 0 0) # Request [same major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 4.5.9.2 0 0 0 0) # Request [same major].[same minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.5.9.7 0 0 0 0) # Request [same major].[same minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.5.9.9 0 0 0 0) # Request [same major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0
+test_write_basic_config_version_file(4.05.06.007 4.9.0.2 0 0 0 0) # Request [same major].[newer minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.0.7 0 0 0 0) # Request [same major].[newer minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.2.0 0 0 0 0) # Request [same major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 4.9.2.2 0 0 0 0) # Request [same major].[newer minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.2.7 0 0 0 0) # Request [same major].[newer minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.2.9 0 0 0 0) # Request [same major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.6.0 0 0 0 0) # Request [same major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 4.9.6.2 0 0 0 0) # Request [same major].[newer minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.6.7 0 0 0 0) # Request [same major].[newer minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.6.9 0 0 0 0) # Request [same major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 4.9.9.2 0 0 0 0) # Request [same major].[newer minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.9.7 0 0 0 0) # Request [same major].[newer minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0
+test_write_basic_config_version_file(4.05.06.007 9.0.0.2 0 0 0 0) # Request [newer major].0.0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.0.7 0 0 0 0) # Request [newer major].0.0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.2.0 0 0 0 0) # Request [newer major].0.[older patch].0
+test_write_basic_config_version_file(4.05.06.007 9.0.2.2 0 0 0 0) # Request [newer major].0.[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.2.7 0 0 0 0) # Request [newer major].0.[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.2.9 0 0 0 0) # Request [newer major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.6.0 0 0 0 0) # Request [newer major].0.[same patch].0
+test_write_basic_config_version_file(4.05.06.007 9.0.6.2 0 0 0 0) # Request [newer major].0.[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.6.7 0 0 0 0) # Request [newer major].0.[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.6.9 0 0 0 0) # Request [newer major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 9.0.9.2 0 0 0 0) # Request [newer major].0.[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.9.7 0 0 0 0) # Request [newer major].0.[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.0.0 0 0 0 0) # Request [newer major].[older minor].0.0
+test_write_basic_config_version_file(4.05.06.007 9.2.0.2 0 0 0 0) # Request [newer major].[older minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.0.7 0 0 0 0) # Request [newer major].[older minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.0.9 0 0 0 0) # Request [newer major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.2.0 0 0 0 0) # Request [newer major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 9.2.2.2 0 0 0 0) # Request [newer major].[older minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.2.7 0 0 0 0) # Request [newer major].[older minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.2.9 0 0 0 0) # Request [newer major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.6.0 0 0 0 0) # Request [newer major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 9.2.6.2 0 0 0 0) # Request [newer major].[older minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.6.7 0 0 0 0) # Request [newer major].[older minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.6.9 0 0 0 0) # Request [newer major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.9.0 0 0 0 0) # Request [newer major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 9.2.9.2 0 0 0 0) # Request [newer major].[older minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.9.7 0 0 0 0) # Request [newer major].[older minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.2.9.9 0 0 0 0) # Request [newer major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.0.0 0 0 0 0) # Request [newer major].[same minor].0.0
+test_write_basic_config_version_file(4.05.06.007 9.5.0.2 0 0 0 0) # Request [newer major].[same minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.0.7 0 0 0 0) # Request [newer major].[same minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.0.9 0 0 0 0) # Request [newer major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.2.0 0 0 0 0) # Request [newer major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 9.5.2.2 0 0 0 0) # Request [newer major].[same minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.2.7 0 0 0 0) # Request [newer major].[same minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.2.9 0 0 0 0) # Request [newer major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.6.0 0 0 0 0) # Request [newer major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 9.5.6.2 0 0 0 0) # Request [newer major].[same minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.6.7 0 0 0 0) # Request [newer major].[same minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.6.9 0 0 0 0) # Request [newer major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.9.0 0 0 0 0) # Request [newer major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 9.5.9.2 0 0 0 0) # Request [newer major].[same minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.9.7 0 0 0 0) # Request [newer major].[same minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.5.9.9 0 0 0 0) # Request [newer major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0
+test_write_basic_config_version_file(4.05.06.007 9.9.0.2 0 0 0 0) # Request [newer major].[newer minor].0.[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.0.7 0 0 0 0) # Request [newer major].[newer minor].0.[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.2.0 0 0 0 0) # Request [newer major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.05.06.007 9.9.2.2 0 0 0 0) # Request [newer major].[newer minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.2.7 0 0 0 0) # Request [newer major].[newer minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.2.9 0 0 0 0) # Request [newer major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.6.0 0 0 0 0) # Request [newer major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.05.06.007 9.9.6.2 0 0 0 0) # Request [newer major].[newer minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.6.7 0 0 0 0) # Request [newer major].[newer minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.6.9 0 0 0 0) # Request [newer major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.05.06.007 9.9.9.2 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.9.7 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.05.06.007 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak]
+
+test_write_basic_config_version_file(4 0...5 1 0 0 0)
+test_write_basic_config_version_file(4 2...5 1 0 0 0)
+test_write_basic_config_version_file(4 2...4 1 0 0 0)
+test_write_basic_config_version_file(4 4...<5 1 1 0 0)
+test_write_basic_config_version_file(4 9...10 0 0 0 0)
+
+test_write_basic_config_version_file(4 0.1...5 1 0 0 0)
+test_write_basic_config_version_file(4 2.1...5 1 0 0 0)
+test_write_basic_config_version_file(4 2.8...5 1 0 0 0)
+test_write_basic_config_version_file(4 2.1...4 1 0 0 0)
+test_write_basic_config_version_file(4 2.8...4 1 0 0 0)
+test_write_basic_config_version_file(4 4.0...<5 1 1 0 0)
+test_write_basic_config_version_file(4 4.8...<5 0 0 0 0)
+test_write_basic_config_version_file(4 4.1...5 0 0 0 0)
+test_write_basic_config_version_file(4 4.8...5 0 0 0 0)
+test_write_basic_config_version_file(4 9.1...10 0 0 0 0)
+test_write_basic_config_version_file(4 9.8...10 0 0 0 0)
+
+
+test_write_basic_config_version_file(4.05 0.1...5 1 0 0 0)
+test_write_basic_config_version_file(4.05 2.1...5 1 0 0 0)
+test_write_basic_config_version_file(4.05 2.8...5 1 0 0 0)
+test_write_basic_config_version_file(4.05 2.1...4 0 0 0 0)
+test_write_basic_config_version_file(4.05 2.8...4 0 0 0 0)
+test_write_basic_config_version_file(4.05 2.8...4.8 1 0 0 0)
+test_write_basic_config_version_file(4.05 4.1...<5 1 1 0 0)
+test_write_basic_config_version_file(4.05 4.8...<5 0 0 0 0)
+test_write_basic_config_version_file(4.05 4.5...4.5.8 1 1 1 0)
+test_write_basic_config_version_file(4.05 4.5...<4.6 1 1 1 0)
+test_write_basic_config_version_file(4.05 4.1...5 1 0 0 0)
+test_write_basic_config_version_file(4.05 4.8...5 0 0 0 0)
+test_write_basic_config_version_file(4.05 9.1...10 0 0 0 0)
+test_write_basic_config_version_file(4.05 9.8...10 0 0 0 0)
+
+
+test_write_basic_config_version_file(4.5.06 0.1...5 1 0 0 0)
+test_write_basic_config_version_file(4.5.06 2.1...5 1 0 0 0)
+test_write_basic_config_version_file(4.5.06 2.8...5 1 0 0 0)
+test_write_basic_config_version_file(4.5.06 2.1...4 0 0 0 0)
+test_write_basic_config_version_file(4.5.06 2.8...4 0 0 0 0)
+test_write_basic_config_version_file(4.5.06 2.8...4.8 1 0 0 0)
+test_write_basic_config_version_file(4.5.06 4.1...<5 1 1 0 0)
+test_write_basic_config_version_file(4.5.06 4.8...<5 0 0 0 0)
+test_write_basic_config_version_file(4.5.06 4.5...4.5.4 0 0 0 0)
+test_write_basic_config_version_file(4.5.06 4.5...4.5.8 1 1 1 0)
+test_write_basic_config_version_file(4.5.06 4.5...<4.6 1 1 1 0)
+test_write_basic_config_version_file(4.5.06 4.1...5 1 0 0 0)
+test_write_basic_config_version_file(4.5.06 4.8...5 0 0 0 0)
+test_write_basic_config_version_file(4.5.06 9.1...10 0 0 0 0)
+test_write_basic_config_version_file(4.5.06 9.8...10 0 0 0 0)
diff --git a/Tests/RunCMake/WriteBasicConfigVersionFile/RunCMakeTest.cmake b/Tests/RunCMake/WriteBasicConfigVersionFile/RunCMakeTest.cmake
index 5db33f7f2..8a9db1564 100644
--- a/Tests/RunCMake/WriteBasicConfigVersionFile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/WriteBasicConfigVersionFile/RunCMakeTest.cmake
@@ -2,3 +2,4 @@ include(RunCMake)
run_cmake(All)
run_cmake(ArchIndependent)
+run_cmake(LeadingZeroes)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS-check.cmake
new file mode 100644
index 000000000..576be11f0
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS-check.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake)
+
+findAttribute(${test} "RemoveHeadersOnCopy" TRUE)
+findAttribute(${test} "CodeSignOnCopy" FALSE)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS.cmake
new file mode 100644
index 000000000..839f8424d
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS.cmake
@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/EmbedAppExtensions.cmake)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS-check.cmake
new file mode 100644
index 000000000..576be11f0
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS-check.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake)
+
+findAttribute(${test} "RemoveHeadersOnCopy" TRUE)
+findAttribute(${test} "CodeSignOnCopy" FALSE)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS.cmake
new file mode 100644
index 000000000..839f8424d
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS.cmake
@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/EmbedAppExtensions.cmake)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions.cmake
new file mode 100644
index 000000000..d7494ea19
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions.cmake
@@ -0,0 +1,21 @@
+add_library(app_extension MODULE Empty.txt)
+set_target_properties(app_extension PROPERTIES
+ LINKER_LANGUAGE CXX
+ BUNDLE YES
+ XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
+ XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
+ XCODE_ATTRIBUTE_ENABLE_BITCODE "NO"
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in"
+ MACOSX_BUNDLE_GUI_IDENTIFIER "com.example.app.app_extension"
+ XCODE_PRODUCT_TYPE "com.apple.product-type.app-extension"
+ XCODE_EXPLICIT_FILE_TYPE "wrapper.app-extension"
+)
+
+add_executable(app MACOSX_BUNDLE main.m)
+add_dependencies(app app_extension)
+set_target_properties(app PROPERTIES
+ XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
+ XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
+ XCODE_EMBED_APP_EXTENSIONS app_extension
+ MACOSX_BUNDLE_GUI_IDENTIFIER "com.example.app"
+)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake
index 9cc03b9f4..dbd3e8774 100644
--- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake
@@ -1,14 +1,4 @@
-function(findAttribute project attr)
- execute_process(
- COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj
- OUTPUT_VARIABLE output_var
- RESULT_VARIABLE result_var
- )
+include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake)
- if(NOT result_var)
- set(RunCMake_TEST_FAILED "${attr} attribute is set" PARENT_SCOPE)
- endif()
-endfunction()
-
-findAttribute(${test} "RemoveHeadersOnCopy")
-findAttribute(${test} "CodeSignOnCopy")
+findAttribute(${test} "RemoveHeadersOnCopy" FALSE)
+findAttribute(${test} "CodeSignOnCopy" FALSE)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake
index 3f62640c9..0f5782066 100644
--- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake
@@ -1,14 +1,4 @@
-function(findAttribute project attr)
- execute_process(
- COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj
- OUTPUT_VARIABLE output_var
- RESULT_VARIABLE result_var
- )
+include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake)
- if(result_var)
- set(RunCMake_TEST_FAILED "${attr} attribute not set" PARENT_SCOPE)
- endif()
-endfunction()
-
-findAttribute(${test} "RemoveHeadersOnCopy")
-findAttribute(${test} "CodeSignOnCopy")
+findAttribute(${test} "RemoveHeadersOnCopy" TRUE)
+findAttribute(${test} "CodeSignOnCopy" TRUE)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake
index 3f62640c9..0f5782066 100644
--- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake
@@ -1,14 +1,4 @@
-function(findAttribute project attr)
- execute_process(
- COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj
- OUTPUT_VARIABLE output_var
- RESULT_VARIABLE result_var
- )
+include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake)
- if(result_var)
- set(RunCMake_TEST_FAILED "${attr} attribute not set" PARENT_SCOPE)
- endif()
-endfunction()
-
-findAttribute(${test} "RemoveHeadersOnCopy")
-findAttribute(${test} "CodeSignOnCopy")
+findAttribute(${test} "RemoveHeadersOnCopy" TRUE)
+findAttribute(${test} "CodeSignOnCopy" TRUE)
diff --git a/Tests/RunCMake/XcodeProject-Embed/Empty.txt b/Tests/RunCMake/XcodeProject-Embed/Empty.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/Empty.txt
diff --git a/Tests/RunCMake/XcodeProject-Embed/Info.plist.in b/Tests/RunCMake/XcodeProject-Embed/Info.plist.in
new file mode 100644
index 000000000..a26f31630
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/Info.plist.in
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleDisplayName</key>
+ <string>SomeExtension</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.example.app.app_extension</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>app</string>
+ <key>CFBundlePackageType</key>
+ <string>XPC!</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0.0</string>
+ <key>CFBundleVersion</key>
+ <string>1.0.0</string>
+ <key>NSExtension</key>
+ <dict>
+ <key>NSExtensionPointIdentifier</key>
+ <string>com.apple.widgetkit-extension</string>
+ <key>NSExtensionPrincipalClass</key>
+ <string>SomeExtensionBrowserViewController</string>
+ </dict>
+</dict>
+</plist>
diff --git a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake
index 0dc1cf31c..e94d084c1 100644
--- a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake
@@ -41,3 +41,34 @@ endfunction()
TestFlagsOn(EmbedFrameworksFlagsOnNoSubdir)
TestFlagsOn(EmbedFrameworksFlagsOnWithSubdir)
+
+
+function(TestAppExtension platform)
+ set(testName EmbedAppExtensions-${platform})
+ if(NOT platform STREQUAL "macOS")
+ set(RunCMake_TEST_OPTIONS -DCMAKE_SYSTEM_NAME=${platform})
+ endif()
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-build)
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+ run_cmake(${testName})
+ run_cmake_command(${testName}-build
+ ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR}
+ --config Debug
+ --target app
+ )
+endfunction()
+
+# Isolate device tests from host architecture selection.
+unset(ENV{CMAKE_OSX_ARCHITECTURES})
+
+if(XCODE_VERSION VERSION_GREATER_EQUAL 8)
+ # The various flag on/off combinations are tested by the EmbedFrameworks...
+ # tests, so we don't duplicate all the combinations here. We only verify the
+ # defaults, which is to remove headers on copy, but not code sign.
+ TestAppExtension(macOS)
+ TestAppExtension(iOS)
+endif()
diff --git a/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake b/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake
new file mode 100644
index 000000000..b1963e248
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake
@@ -0,0 +1,19 @@
+cmake_policy(VERSION 3.1...3.20)
+
+function(findAttribute project attr expectPresent)
+ execute_process(
+ COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj
+ OUTPUT_VARIABLE output_var
+ RESULT_VARIABLE result_var
+ )
+
+ if(${expectPresent})
+ if(result_var)
+ set(RunCMake_TEST_FAILED "${attr} attribute is not set" PARENT_SCOPE)
+ endif()
+ else()
+ if(NOT result_var)
+ set(RunCMake_TEST_FAILED "${attr} attribute is set" PARENT_SCOPE)
+ endif()
+ endif()
+endfunction()
diff --git a/Tests/RunCMake/XcodeProject/InheritedParameters-check.cmake b/Tests/RunCMake/XcodeProject/InheritedParameters-check.cmake
new file mode 100644
index 000000000..4fe42acb0
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/InheritedParameters-check.cmake
@@ -0,0 +1,49 @@
+set(xcProjectFile "${RunCMake_TEST_BINARY_DIR}/InheritedParameters.xcodeproj/project.pbxproj")
+if(NOT EXISTS "${xcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${xcProjectFile} does not exist.")
+ return()
+endif()
+
+set(found_inherited_GCC_PREPROCESSOR_DEFINITIONS 1)
+set(found_inherited_OTHER_CFLAGS 1)
+set(found_inherited_OTHER_LDFLAGS 1)
+
+file(STRINGS "${xcProjectFile}" lines)
+foreach(line IN LISTS lines)
+
+ if(line MATCHES [[GCC_PREPROCESSOR_DEFINITIONS]])
+ if(NOT line MATCHES [["\$\(inherited\)"]])
+ string(APPEND relevant_lines " ${line}\n")
+ set(found_inherited_GCC_PREPROCESSOR_DEFINITIONS 0)
+ endif()
+ endif()
+
+ if(line MATCHES [[OTHER_CFLAGS]])
+ if(NOT line MATCHES [["\$\(inherited\)"]])
+ string(APPEND relevant_lines " ${line}\n")
+ set(found_inherited_OTHER_CFLAGS 0)
+ endif()
+ endif()
+
+ if(line MATCHES [[OTHER_LDFLAGS]])
+ if(NOT line MATCHES [["\$\(inherited\)"]])
+ string(APPEND relevant_lines " ${line}\n")
+ set(found_inherited_OTHER_LDFLAGS 0)
+ endif()
+ endif()
+
+endforeach()
+
+if(NOT found_inherited_GCC_PREPROCESSOR_DEFINITIONS)
+ string(APPEND RunCMake_TEST_FAILED "Found missing inherited value for GCC_PREPROCESSOR_DEFINITIONS in\n ${xcProjectFile}\n")
+endif()
+if(NOT found_inherited_OTHER_CFLAGS)
+ string(APPEND RunCMake_TEST_FAILED "Found missing inherited value for OTHER_CFLAGS in\n ${xcProjectFile}\n")
+endif()
+if(NOT found_inherited_OTHER_LDFLAGS)
+ string(APPEND RunCMake_TEST_FAILED "Found missing inherited value for OTHER_LDFLAGS in\n ${xcProjectFile}\n")
+endif()
+
+if(RunCMake_TEST_FAILED)
+ string(APPEND RunCMake_TEST_FAILED "Relevant lines include\n${relevant_lines}")
+endif()
diff --git a/Tests/RunCMake/XcodeProject/InheritedParameters.cmake b/Tests/RunCMake/XcodeProject/InheritedParameters.cmake
new file mode 100644
index 000000000..5b8ec7117
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/InheritedParameters.cmake
@@ -0,0 +1,8 @@
+enable_language(C)
+
+add_compile_definitions(TEST_INHERITTEST)
+string(APPEND CMAKE_C_FLAGS " -DTESTFLAG=\\\"TEST_INHERITTEST\\\"")
+
+add_executable(inherit_test main.c)
+
+target_link_libraries(inherit_test PRIVATE "TEST_INHERITTEST")
diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
index 8b0321657..26714c47f 100644
--- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
@@ -4,6 +4,7 @@ run_cmake(ExplicitCMakeLists)
run_cmake(ImplicitCMakeLists)
run_cmake(InterfaceLibSources)
run_cmake_with_options(SearchPaths -DCMAKE_CONFIGURATION_TYPES=Debug)
+run_cmake(InheritedParameters)
run_cmake(XcodeFileType)
run_cmake(XcodeAttributeLocation)
@@ -387,4 +388,30 @@ if(XCODE_VERSION VERSION_GREATER_EQUAL 8)
XcodeRemoveExcessiveISystemSDK(iphoneos)
XcodeRemoveExcessiveISystemSDK(iphonesimulator)
endif()
+
+if (XCODE_VERSION VERSION_GREATER_EQUAL 7.3)
+ function(xctest_add_bundle_test SystemName SDK BuildSystemVersion ExpectedOutputDir)
+ set(RunCMake_TEST_BINARY_DIR
+ ${RunCMake_BINARY_DIR}/DeploymentTarget-${SystemName}-${SDK}-${BuildSystemVersion}-build)
+ set(RunCMake_TEST_OPTIONS
+ "-DCMAKE_SYSTEM_NAME=${SystemName}"
+ "-DCMAKE_OSX_SYSROOT=${SDK}"
+ "-DTEST_EXPECTED_OUTPUT_DIR=${ExpectedOutputDir}")
+ unset(RunCMake_GENERATOR_TOOLSET)
+ if(BuildSystemVersion)
+ set(RunCMake_GENERATOR_TOOLSET "buildsystem=${BuildSystemVersion}")
+ endif()
+ run_cmake(XCTestAddBundle)
+ endfunction()
+
+ if(XCODE_VERSION VERSION_GREATER_EQUAL 12)
+ xctest_add_bundle_test(Darwin macosx "1" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns")
+ xctest_add_bundle_test(Darwin macosx "12" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns")
+ xctest_add_bundle_test(iOS iphoneos "1" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns")
+ xctest_add_bundle_test(iOS iphoneos "12" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>")
+ else()
+ xctest_add_bundle_test(Darwin macosx "" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns")
+ xctest_add_bundle_test(iOS iphoneos "" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns")
+ endif()
+endif()
# Please add macOS-only tests above before the device-specific tests.
diff --git a/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake b/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake
new file mode 100644
index 000000000..444c730bb
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake
@@ -0,0 +1,17 @@
+enable_language(Swift)
+find_package(XCTest REQUIRED)
+
+add_executable(TestedApp MACOSX_BUNDLE EXCLUDE_FROM_ALL foo.swift)
+
+xctest_add_bundle(TestingAppBundle TestedApp foo.swift)
+
+get_target_property(_lib_output_dir TestingAppBundle LIBRARY_OUTPUT_DIRECTORY)
+
+if (NOT DEFINED TEST_EXPECTED_OUTPUT_DIR)
+ message(FATAL_ERROR "Testing variable TEST_EXPECTED_OUTPUT_DIR is not set")
+endif()
+
+if (NOT _lib_output_dir STREQUAL TEST_EXPECTED_OUTPUT_DIR)
+ message(SEND_ERROR "Property LIBRARY_OUTPUT_DIRECTORY is expected to be ${TEST_EXPECTED_OUTPUT_DIR} "
+ "but was ${_lib_output_dir}")
+endif()
diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
index 9c59b4b75..ad6b2586c 100644
--- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
@@ -43,3 +43,20 @@ if(NOT RunCMake_GENERATOR STREQUAL "Ninja Multi-Config")
unset(RunCMake_TEST_BINARY_DIR)
unset(RunCMake_TEST_NO_CLEAN)
endif()
+
+function(test_genex name)
+ run_cmake(${name})
+
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${name}-build")
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${name}-build ${CMAKE_COMMAND} --build .)
+
+ if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/wdir/touched")
+ message(SEND_ERROR "File not created by target-dependent add_custom_command()!")
+ endif()
+
+ unset(RunCMake_TEST_NO_CLEAN)
+ unset(RunCMake_TEST_BINARY_DIR)
+endfunction()
+
+test_genex(TargetGenexEvent)
diff --git a/Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake b/Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake
new file mode 100644
index 000000000..8591b74fc
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake
@@ -0,0 +1,10 @@
+add_custom_target(target ALL)
+set_target_properties(target PROPERTIES COMPILE_DEFINITIONS "touched" COMPILE_OPTIONS "${CMAKE_BINARY_DIR}/wdir")
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/wdir")
+
+add_custom_command(
+ TARGET target
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E touch $<TARGET_PROPERTY:COMPILE_DEFINITIONS>
+ WORKING_DIRECTORY $<TARGET_PROPERTY:COMPILE_OPTIONS>
+)
diff --git a/Tests/RunCMake/add_executable/RunCMakeTest.cmake b/Tests/RunCMake/add_executable/RunCMakeTest.cmake
index 88916b71f..70a68f265 100644
--- a/Tests/RunCMake/add_executable/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_executable/RunCMakeTest.cmake
@@ -2,6 +2,4 @@ include(RunCMake)
run_cmake(NoSources)
run_cmake(OnlyObjectSources)
-if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
- run_cmake(NoSourcesButLinkObjects)
-endif()
+run_cmake(NoSourcesButLinkObjects)
diff --git a/Tests/RunCMake/add_library/RunCMakeTest.cmake b/Tests/RunCMake/add_library/RunCMakeTest.cmake
index dfadb8fc1..3283625e4 100644
--- a/Tests/RunCMake/add_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_library/RunCMakeTest.cmake
@@ -16,11 +16,9 @@ run_cmake(SHAREDwithOnlyObjectSources)
run_cmake(MODULEwithOnlyObjectSources)
run_cmake(UNKNOWNwithOnlyObjectSources)
-if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
- run_cmake(INTERFACEwithNoSourcesButLinkObjects)
- run_cmake(OBJECTwithNoSourcesButLinkObjects)
- run_cmake(STATICwithNoSourcesButLinkObjects)
- run_cmake(SHAREDwithNoSourcesButLinkObjects)
- run_cmake(MODULEwithNoSourcesButLinkObjects)
- run_cmake(UNKNOWNwithNoSourcesButLinkObjects)
-endif()
+run_cmake(INTERFACEwithNoSourcesButLinkObjects)
+run_cmake(OBJECTwithNoSourcesButLinkObjects)
+run_cmake(STATICwithNoSourcesButLinkObjects)
+run_cmake(SHAREDwithNoSourcesButLinkObjects)
+run_cmake(MODULEwithNoSourcesButLinkObjects)
+run_cmake(UNKNOWNwithNoSourcesButLinkObjects)
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-component-stdout.txt
index 7d76ed959..169f0ccb2 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-component-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-component-stdout.txt
@@ -1,4 +1,5 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- Install component: "Unspecified"
-- sub
-- top$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-stdout.txt
index 35b0bb5e1..426114b59 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-stdout.txt
@@ -1,3 +1,4 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- sub
-- top$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-component-stdout.txt
index 4b39789f7..b26500ef6 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-component-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-component-stdout.txt
@@ -1,4 +1,5 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- Install component: "Unspecified"
-- top
-- sub$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-stdout.txt
index 8f3a5f71d..fcd556cb4 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-stdout.txt
@@ -1,3 +1,4 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- top
-- sub$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-component-stdout.txt
index 4b39789f7..b26500ef6 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-component-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-component-stdout.txt
@@ -1,4 +1,5 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- Install component: "Unspecified"
-- top
-- sub$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt
index 8f3a5f71d..fcd556cb4 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt
@@ -1,3 +1,4 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- top
-- sub$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-component-stdout.txt
index 4b39789f7..b26500ef6 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-component-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-component-stdout.txt
@@ -1,4 +1,5 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- Install component: "Unspecified"
-- top
-- sub$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-stdout.txt
index 8f3a5f71d..fcd556cb4 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-stdout.txt
@@ -1,3 +1,4 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- top
-- sub$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-component-stdout.txt
index f7a331df2..c6020bd46 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-component-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-component-stdout.txt
@@ -1,3 +1,4 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- Install component: "Unspecified"
-- sub$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-stdout.txt
index 6f22ae24d..658386b62 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-stdout.txt
@@ -1,2 +1,3 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- sub$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-component-stdout.txt
index 157ab37e2..ad070d580 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-component-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-component-stdout.txt
@@ -1,3 +1,4 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- Install component: "Unspecified"
-- top$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-stdout.txt
index 9e15872bd..5a44e46af 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-stdout.txt
@@ -1,2 +1,3 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- top$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-component-stdout.txt
index 4b39789f7..b26500ef6 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-component-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-component-stdout.txt
@@ -1,4 +1,5 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- Install component: "Unspecified"
-- top
-- sub$
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-stdout.txt
index 8f3a5f71d..fcd556cb4 100644
--- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-stdout.txt
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-stdout.txt
@@ -1,3 +1,4 @@
-^-- Install configuration: "[^\n]*"
+^-- Install configuration: "[^
+]*"
-- top
-- sub$
diff --git a/Tests/RunCMake/build_command/ParallelLevel.cmake b/Tests/RunCMake/build_command/ParallelLevel.cmake
new file mode 100644
index 000000000..1d1e525f7
--- /dev/null
+++ b/Tests/RunCMake/build_command/ParallelLevel.cmake
@@ -0,0 +1,5 @@
+cmake_policy(SET CMP0061 NEW)
+build_command(cmd PARALLEL_LEVEL 1)
+if(NOT cmd MATCHES [[ --parallel "1"]])
+ message(FATAL_ERROR "Cannot find the --parallel flag")
+endif()
diff --git a/Tests/RunCMake/build_command/RunCMakeTest.cmake b/Tests/RunCMake/build_command/RunCMakeTest.cmake
index c3bef4c81..030db0b5c 100644
--- a/Tests/RunCMake/build_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/build_command/RunCMakeTest.cmake
@@ -14,3 +14,5 @@ if(RunCMake_GENERATOR MATCHES "Make")
else()
run_cmake(CMP0061-OLD-other)
endif()
+
+run_cmake(ParallelLevel)
diff --git a/Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt b/Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt
index 2fd194dc9..674ff1dd0 100644
--- a/Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt
+++ b/Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt
@@ -5,7 +5,7 @@
-- Immediate Message: cancelCall='cmake_language;DEFER;CANCEL_CALL;toBeCancelled'
-- Immediate Message: getCallIds2='cmake_language;DEFER;GET_CALL_IDS;ids'
-- Immediate Message: messageIds2='cmake_language;EVAL;CODE;message\(STATUS "Deferred Message: ids='\${ids}'"\)'
--- Immediate Message: toBeCancelled='message;STATUS;Cancelled Message'
+-- Immediate Message: toBeCancelled='message;STATUS;Canceled Message'
-- Immediate Message: message3='message;STATUS;Final Deferred Message'
-- First Deferred Message
-- Deferred Message: ids='messageIds1;cancelCall;getCallIds2;messageIds2;toBeCancelled;message3'
diff --git a/Tests/RunCMake/cmake_language/defer_call_ids.cmake b/Tests/RunCMake/cmake_language/defer_call_ids.cmake
index 287489417..fd5bc1792 100644
--- a/Tests/RunCMake/cmake_language/defer_call_ids.cmake
+++ b/Tests/RunCMake/cmake_language/defer_call_ids.cmake
@@ -4,7 +4,7 @@ cmake_language(DEFER ID messageIds1 CALL cmake_language EVAL CODE [[message(STAT
cmake_language(DEFER ID cancelCall CALL cmake_language DEFER CANCEL_CALL toBeCancelled)
cmake_language(DEFER ID getCallIds2 CALL cmake_language DEFER GET_CALL_IDS ids)
cmake_language(DEFER ID messageIds2 CALL cmake_language EVAL CODE [[message(STATUS "Deferred Message: ids='${ids}'")]])
-cmake_language(DEFER ID toBeCancelled CALL message STATUS "Cancelled Message")
+cmake_language(DEFER ID toBeCancelled CALL message STATUS "Canceled Message")
cmake_language(DEFER ID message3 CALL message STATUS "Final Deferred Message")
cmake_language(DEFER GET_CALL_IDS ids)
message(STATUS "Immediate Message: ids='${ids}'")
diff --git a/Tests/RunCMake/configure_file/NoSourcePermissions.cmake b/Tests/RunCMake/configure_file/NoSourcePermissions.cmake
index c6ad1311e..85533c40c 100644
--- a/Tests/RunCMake/configure_file/NoSourcePermissions.cmake
+++ b/Tests/RunCMake/configure_file/NoSourcePermissions.cmake
@@ -1,7 +1,7 @@
configure_file(NoSourcePermissions.sh NoSourcePermissions.sh.out
NO_SOURCE_PERMISSIONS)
-if (UNIX)
+if (UNIX AND NOT MSYS)
execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/NoSourcePermissions.sh.out
RESULT_VARIABLE result)
if (result EQUAL "0")
diff --git a/Tests/RunCMake/configure_file/SourcePermissions.cmake b/Tests/RunCMake/configure_file/SourcePermissions.cmake
index c4d3d6131..f8c506ab3 100644
--- a/Tests/RunCMake/configure_file/SourcePermissions.cmake
+++ b/Tests/RunCMake/configure_file/SourcePermissions.cmake
@@ -6,7 +6,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt
WORLD_READ
)
-if (CMAKE_HOST_UNIX)
+if (CMAKE_HOST_UNIX AND NOT MSYS)
find_program(STAT_EXECUTABLE NAMES stat)
if(NOT STAT_EXECUTABLE)
return()
diff --git a/Tests/RunCMake/ctest_build/ParallelLevel-check.cmake b/Tests/RunCMake/ctest_build/ParallelLevel-check.cmake
new file mode 100644
index 000000000..f45d2a29f
--- /dev/null
+++ b/Tests/RunCMake/ctest_build/ParallelLevel-check.cmake
@@ -0,0 +1,11 @@
+file(GLOB build_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Build.xml")
+if(build_xml_file)
+ file(STRINGS "${build_xml_file}" build_cmd LIMIT_COUNT 1 REGEX "<BuildCommand>")
+ if(NOT build_cmd MATCHES [[ --parallel "1"]])
+ set(RunCMake_TEST_FAILED
+ "Build.xml does not have expected build command with --parallel flag"
+ )
+ endif()
+else()
+ set(RunCMake_TEST_FAILED "Build.xml not found")
+endif()
diff --git a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake
index 072fbac22..511cd71fb 100644
--- a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake
@@ -10,6 +10,7 @@ function(run_ctest_build CASE_NAME)
endfunction()
run_ctest_build(BuildQuiet QUIET)
+run_ctest_build(ParallelLevel PARALLEL_LEVEL 1)
function(run_BuildFailure)
set(CASE_CMAKELISTS_SUFFIX_CODE [[
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt
index b54220cff..acda9e26e 100644
--- a/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt
+++ b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt
@@ -1,5 +1,12 @@
-Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-build
+Test project [^
+]*/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-build(
+[^*][^
+]*)*
+test 1
Start 1: RunCMakeVersion
++(
+[^*][^
+]*)*
1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt
index c221eed72..4081f9876 100644
--- a/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt
+++ b/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt
@@ -1,5 +1,12 @@
-Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadPass-build
+Test project [^
+]*/Tests/RunCMake/ctest_test/CTestTestLoadPass-build(
+[^*][^
+]*)*
+test 1
Start 1: RunCMakeVersion
++(
+[^*][^
+]*)*
1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt
index 2af3838ed..2f4468f9f 100644
--- a/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt
+++ b/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt
@@ -1,6 +1,13 @@
-Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadWait-build
+Test project [^
+]*/Tests/RunCMake/ctest_test/CTestTestLoadWait-build(
+[^*][^
+]*)*
\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 4, Smallest test RunCMakeVersion requires 1\*\*\*\*\*
+test 1
Start 1: RunCMakeVersion
++(
+[^*][^
+]*)*
1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/ctest_test/OutputJUnit-check.cmake b/Tests/RunCMake/ctest_test/OutputJUnit-check.cmake
new file mode 100644
index 000000000..00310a4f8
--- /dev/null
+++ b/Tests/RunCMake/ctest_test/OutputJUnit-check.cmake
@@ -0,0 +1,24 @@
+file(GLOB junit_xml_file "${RunCMake_TEST_BINARY_DIR}/junit.xml")
+if(junit_xml_file)
+ file(READ "${junit_xml_file}" junit_xml LIMIT 4096)
+ if(NOT "${junit_xml}" MATCHES "tests=\"1\"")
+ set(RunCMake_TEST_FAILED "tests=\"1\" not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "failures=\"0\"")
+ set(RunCMake_TEST_FAILED "failures=\"0\" not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "disabled=\"0\"")
+ set(RunCMake_TEST_FAILED "disabled=\"0\" not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "skipped=\"0\"")
+ set(RunCMake_TEST_FAILED "skipped=\"0\" not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "<testcase name=\"RunCMakeVersion\" classname=\"RunCMakeVersion\"")
+ set(RunCMake_TEST_FAILED "RunCMakeVersion not found when expected")
+ endif()
+ if(NOT "${junit_xml}" MATCHES "<system-out>cmake version")
+ set(RunCMake_TEST_FAILED "<system-out>cmake version not found when expected")
+ endif()
+else()
+ set(RunCMake_TEST_FAILED "junit.xml not found")
+endif()
diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
index b82335f1b..f07a12b77 100644
--- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
@@ -18,6 +18,7 @@ run_ctest_test(TestQuiet QUIET)
#
# Spoof a load average value to make these tests more reliable.
set(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING} 5)
+set(RunCTest_VERBOSE_FLAG -VV)
# Verify that new tests are started when the load average falls below
# our threshold.
@@ -53,6 +54,7 @@ run_ctest_test(TestLoadOrder TEST_LOAD "ERR4")
unset(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING})
unset(CASE_CTEST_TEST_LOAD)
+unset(RunCTest_VERBOSE_FLAG)
function(run_TestChangeId)
set(CASE_TEST_PREFIX_CODE [[
@@ -144,3 +146,38 @@ set_property(TEST RunCMakeVersion PROPERTY ENVIRONMENT "ENV1=env1;ENV2=env2")
run_ctest(TestEnvironment)
endfunction()
run_environment()
+
+# test for OUTPUT_JUNIT
+run_ctest_test(OutputJUnit OUTPUT_JUNIT junit.xml REPEAT UNTIL_FAIL:2)
+
+# Verify that extra measurements get reported.
+function(run_measurements)
+ set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(
+ NAME double_measurement
+ COMMAND ${CMAKE_COMMAND} -E
+ echo <DartMeasurement type="numeric/double" name="my_custom_value">1.4847</DartMeasurement>)
+add_test(
+ NAME img_measurement
+ COMMAND ${CMAKE_COMMAND} -E
+ echo <DartMeasurementFile name="TestImage" type="image/png">]] ${IMAGE_DIR}/cmake-logo-16.png [[</DartMeasurementFile>)
+add_test(
+ NAME file_measurement
+ COMMAND ${CMAKE_COMMAND} -E
+ echo <DartMeasurementFile name="my_test_input_data" type="file">]] ${IMAGE_DIR}/cmake-logo-16.png [[</DartMeasurementFile>)
+ ]])
+ run_ctest(TestMeasurements)
+endfunction()
+run_measurements()
+
+# Verify that test output can override the Completion Status.
+function(run_completion_status)
+ set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(
+ NAME custom_details
+ COMMAND ${CMAKE_COMMAND} -E
+ echo test output\n<CTestDetails>CustomDetails</CTestDetails>\nmore output)
+ ]])
+ run_ctest(TestCompletionStatus)
+endfunction()
+run_completion_status()
diff --git a/Tests/RunCMake/ctest_test/TestCompletionStatus-check.cmake b/Tests/RunCMake/ctest_test/TestCompletionStatus-check.cmake
new file mode 100644
index 000000000..10de2edf0
--- /dev/null
+++ b/Tests/RunCMake/ctest_test/TestCompletionStatus-check.cmake
@@ -0,0 +1,16 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/TAG" _tag)
+string(REGEX REPLACE "^([^\n]*)\n.*$" "\\1" _date "${_tag}")
+file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/${_date}/Test.xml" _test_contents)
+
+# Check custom completion status.
+if(NOT _test_contents MATCHES [[<Value>CustomDetails</Value>]])
+ string(APPEND RunCMake_TEST_FAILED
+ "Could not find expected <Value>CustomDetails</Value> in Test.xml")
+endif()
+# Check test output.
+if(NOT _test_contents MATCHES "test output")
+ string(APPEND RunCMake_TEST_FAILED "Could not find expected string 'test output' in Test.xml")
+endif()
+if(NOT _test_contents MATCHES "more output")
+ string(APPEND RunCMake_TEST_FAILED "Could not find expected string 'more output' in Test.xml")
+endif()
diff --git a/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt
index c4fd35b4a..8d21f916e 100644
--- a/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt
@@ -1,5 +1,12 @@
-Test project .*/Tests/RunCMake/ctest_test/TestLoadInvalid-build
+Test project [^
+]*/Tests/RunCMake/ctest_test/TestLoadInvalid-build(
+[^*][^
+]*)*
+test 1
Start 1: RunCMakeVersion
++(
+[^*][^
+]*)*
1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt
index 22da09211..1ef5f5acc 100644
--- a/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt
@@ -1,5 +1,12 @@
-Test project .*/Tests/RunCMake/ctest_test/TestLoadOrder-build
+Test project [^
+]*/Tests/RunCMake/ctest_test/TestLoadOrder-build(
+[^*][^
+]*)*
+test 1
Start 1: RunCMakeVersion
++(
+[^*][^
+]*)*
1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt
index e5048f4b4..f3e7cd1ef 100644
--- a/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt
@@ -1,5 +1,12 @@
-Test project .*/Tests/RunCMake/ctest_test/TestLoadPass-build
+Test project [^
+]*/Tests/RunCMake/ctest_test/TestLoadPass-build(
+[^*][^
+]*)*
+test 1
Start 1: RunCMakeVersion
++(
+[^*][^
+]*)*
1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt
index 07f4ed361..fc329586a 100644
--- a/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt
+++ b/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt
@@ -1,6 +1,13 @@
-Test project .*/Tests/RunCMake/ctest_test/TestLoadWait-build
+Test project [^
+]*/Tests/RunCMake/ctest_test/TestLoadWait-build(
+[^*][^
+]*)*
\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 2, Smallest test RunCMakeVersion requires 1\*\*\*\*\*
+test 1
Start 1: RunCMakeVersion
++(
+[^*][^
+]*)*
1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec
+
100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake
new file mode 100644
index 000000000..0095db0de
--- /dev/null
+++ b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake
@@ -0,0 +1,22 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/TAG" _tag)
+string(REGEX REPLACE "^([^\n]*)\n.*$" "\\1" _date "${_tag}")
+file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/${_date}/Test.xml" _test_contents)
+
+# Check double measurement.
+if(NOT _test_contents MATCHES [[NamedMeasurement type="numeric/double" name="my_custom_value"]])
+ string(APPEND RunCMake_TEST_FAILED
+ "Could not find expected <NamedMeasurement> tag for type='numeric/double' in Test.xml")
+endif()
+if(NOT _test_contents MATCHES "<Value>1.4847</Value>")
+ string(APPEND RunCMake_TEST_FAILED "Could not find expected measurement value in Test.xml")
+endif()
+# Check img measurement.
+if(NOT _test_contents MATCHES [[NamedMeasurement name="TestImage" type="image/png" encoding="base64"]])
+ string(APPEND RunCMake_TEST_FAILED
+ "Could not find expected <NamedMeasurement> tag for type='image/png' in Test.xml")
+endif()
+# Check file measurement.
+if(NOT _test_contents MATCHES [[NamedMeasurement name="my_test_input_data" encoding="base64" compression="tar/gzip" filename="cmake-logo-16.png" type="file"]])
+ string(APPEND RunCMake_TEST_FAILED
+ "Could not find expected <NamedMeasurement> tag for type='file' in Test.xml")
+endif()
diff --git a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake
index c7bff15c2..18deb8951 100644
--- a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake
@@ -14,6 +14,6 @@ if(UNIX)
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
-if(NOT WIN32 AND NOT "${uid}" STREQUAL "0")
+if(NOT WIN32 AND NOT MSYS AND NOT "${uid}" STREQUAL "0")
run_cmake(CHMOD-write-only)
endif()
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake
index 763d57ce3..07679b711 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake
@@ -11,15 +11,36 @@ function(run_install_test case)
run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config Debug)
# Check "all" components.
set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-all)
- run_cmake_command(${case}-all ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -P cmake_install.cmake)
+ run_cmake_command(${case}-all ${CMAKE_COMMAND} --install . --prefix ${CMAKE_INSTALL_PREFIX} --config Debug)
+endfunction()
+
+# Function to check the contents of the output files.
+function(check_contents filename contents_regex)
+ if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
+ file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
+ if(NOT contents MATCHES "${contents_regex}")
+ string(APPEND RunCMake_TEST_FAILED "File contents:
+ ${contents}
+do not match what we expected:
+ ${contents_regex}
+in file:
+ ${CMAKE_INSTALL_PREFIX}/${filename}\n")
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+ endif()
+ else()
+ string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+ endif()
endfunction()
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
if(NOT CMake_INSTALL_NAME_TOOL_BUG)
run_install_test(macos)
+ run_install_test(macos-rpath)
run_install_test(macos-unresolved)
run_install_test(macos-conflict)
run_install_test(macos-notfile)
+ run_install_test(file-filter)
endif()
run_cmake(project)
run_cmake(badargs1)
@@ -29,6 +50,7 @@ elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
run_install_test(windows-unresolved)
run_install_test(windows-conflict)
run_install_test(windows-notfile)
+ run_install_test(file-filter)
run_cmake(project)
run_cmake(badargs1)
run_cmake(badargs2)
@@ -41,6 +63,7 @@ elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
if(NOT CMAKE_C_COMPILER_ID MATCHES "^XL")
run_install_test(linux)
+ run_install_test(file-filter)
endif()
run_install_test(linux-unresolved)
run_install_test(linux-conflict)
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2.cmake
index ac6af8576..f80829dc1 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2.cmake
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2.cmake
@@ -11,5 +11,7 @@ file(GET_RUNTIME_DEPENDENCIES
PRE_EXCLUDE_REGEXES
POST_INCLUDE_REGEXES
POST_EXCLUDE_REGEXES
+ POST_INCLUDE_FILES
+ POST_EXCLUDE_FILES
)
message(FATAL_ERROR "This message should not be displayed")
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-all-check.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-all-check.cmake
new file mode 100644
index 000000000..9622f877c
--- /dev/null
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-all-check.cmake
@@ -0,0 +1,28 @@
+if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
+ set(_check
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep1\.so]]
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep2\.so]]
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep3\.so]]
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep4\.so]]
+ )
+ check_contents(deps/deps.txt "^${_check}$")
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
+ set(_check
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep1\.dylib]]
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep2\.dylib]]
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep3\.dylib]]
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep4\.dylib]]
+ )
+ check_contents(deps/deps.txt "^${_check}$")
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+ set(_check
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/(lib)?dep1\.dll]]
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/(lib)?dep2\.dll]]
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/(lib)?dep3\.dll]]
+ [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/(lib)?dep4\.dll]]
+ )
+ check_contents(deps/deps.txt "^${_check}$")
+endif()
+
+check_contents(deps/udeps.txt "^$")
+check_contents(deps/cdeps.txt "^$")
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter.cmake
new file mode 100644
index 000000000..fef084b96
--- /dev/null
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter.cmake
@@ -0,0 +1,104 @@
+enable_language(C)
+
+set(dep_list)
+set(import_list)
+set(call_list)
+foreach(i 1 2 3 4 5 6 7 8 9)
+ file(WRITE "${CMAKE_BINARY_DIR}/dep${i}.c"
+"#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ void dep${i}(void)
+{
+}
+")
+ add_library(dep${i} SHARED "${CMAKE_BINARY_DIR}/dep${i}.c")
+ list(APPEND dep_list dep${i})
+ string(APPEND import_list "EXE_IMPORT extern void dep${i}(void);\n")
+ string(APPEND call_list " dep${i}();\n")
+endforeach()
+set_target_properties(dep5 PROPERTIES
+ VERSION 1.2.3
+ SOVERSION 1
+ )
+
+file(WRITE "${CMAKE_BINARY_DIR}/main.c"
+"#ifdef _WIN32
+# define EXE_IMPORT __declspec(dllimport)
+#else
+# define EXE_IMPORT
+#endif
+
+${import_list}
+int main(void)
+{
+${call_list}
+ return 0;
+}
+")
+
+add_executable(exe "${CMAKE_BINARY_DIR}/main.c")
+target_link_libraries(exe PRIVATE ${dep_list})
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set_property(TARGET exe PROPERTY INSTALL_RPATH "\${ORIGIN}/../lib")
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set_property(TARGET exe PROPERTY INSTALL_RPATH "@loader_path/../lib")
+endif()
+
+install(TARGETS exe ${dep_list})
+
+install(CODE
+ [[
+ function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile)
+ file(GET_RUNTIME_DEPENDENCIES
+ RESOLVED_DEPENDENCIES_VAR deps
+ UNRESOLVED_DEPENDENCIES_VAR udeps
+ CONFLICTING_DEPENDENCIES_PREFIX cdeps
+ PRE_INCLUDE_REGEXES "dep[123456789]"
+ PRE_EXCLUDE_REGEXES ".*"
+ POST_INCLUDE_REGEXES "dep9"
+ POST_INCLUDE_FILES
+ "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:dep1>"
+ "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:dep1>"
+ "${CMAKE_INSTALL_PREFIX}/bin/../bin/$<TARGET_FILE_NAME:dep2>"
+ "${CMAKE_INSTALL_PREFIX}/bin/../lib/$<TARGET_FILE_NAME:dep2>"
+ "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:dep3>"
+ "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:dep3>"
+ "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:dep8>"
+ "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:dep8>"
+ POST_EXCLUDE_FILES
+ "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:dep3>"
+ "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:dep3>"
+ "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:dep5>"
+ "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:dep5>"
+ "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:dep6>"
+ "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:dep6>"
+ "${CMAKE_INSTALL_PREFIX}/bin/../bin/$<TARGET_FILE_NAME:dep7>"
+ "${CMAKE_INSTALL_PREFIX}/bin/../lib/$<TARGET_FILE_NAME:dep7>"
+ POST_EXCLUDE_FILES_STRICT
+ "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:dep8>"
+ "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:dep8>"
+ "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:dep9>"
+ "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:dep9>"
+ ${ARGN}
+ )
+ list(SORT deps)
+ list(SORT udeps)
+ list(SORT cdeps_FILENAMES)
+ file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}")
+ file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}")
+ file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "")
+ foreach(cdep IN LISTS cdeps_FILENAMES)
+ set(cdep_values ${cdeps_${cdep}})
+ list(SORT cdep_values)
+ file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n")
+ endforeach()
+ endfunction()
+
+ exec_get_runtime_dependencies(
+ deps.txt udeps.txt cdeps.txt
+ EXECUTABLES
+ "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>"
+ )
+ ]])
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake
index 381b60291..d3d1cd6e8 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake
@@ -1,21 +1,3 @@
-function(check_contents filename contents_regex)
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
- file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
- if(NOT contents MATCHES "${contents_regex}")
- string(APPEND RunCMake_TEST_FAILED "File contents:
- ${contents}
-do not match what we expected:
- ${contents_regex}
-in file:
- ${CMAKE_INSTALL_PREFIX}/${filename}\n")
- set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
- endif()
- else()
- string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
- set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
- endif()
-endfunction()
-
set(_check
[[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/libtest_rpath\.so]]
[[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/libtest_runpath\.so]]
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt
index d9758c579..5b863220a 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt
@@ -1,5 +1,2 @@
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
- file Failed to run objdump on:
-
- [^
-]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-build/root-all/bin/\.\./lib/libtest\.so$
+ file Could not resolve file libtest\.so$
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-all-check.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-all-check.cmake
index e7cdbf66f..e9ff9f6e7 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-all-check.cmake
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-all-check.cmake
@@ -1,21 +1,3 @@
-function(check_contents filename contents_regex)
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
- file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
- if(NOT contents MATCHES "${contents_regex}")
- string(APPEND RunCMake_TEST_FAILED "File contents:
- ${contents}
-do not match what we expected:
- ${contents_regex}
-in file:
- ${CMAKE_INSTALL_PREFIX}/${filename}\n")
- set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
- endif()
- else()
- string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
- set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
- endif()
-endfunction()
-
function(set_with_libsystem var)
set(_tmp "${ARGN}")
if(EXISTS "/usr/lib/libSystem.B.dylib")
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-rpath.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-rpath.cmake
new file mode 100644
index 000000000..798045f4c
--- /dev/null
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-rpath.cmake
@@ -0,0 +1,35 @@
+enable_language(C)
+
+file(WRITE "${CMAKE_BINARY_DIR}/toplib.c" "extern void sublib1(void);\nextern void sublib2(void);\nvoid toplib(void)\n{\n sublib1();\n sublib2();\n}\n")
+add_library(toplib SHARED "${CMAKE_BINARY_DIR}/toplib.c")
+file(WRITE "${CMAKE_BINARY_DIR}/sublib1.c" "extern void sublib2(void);\nvoid sublib1(void)\n{\n sublib2();\n}\n")
+add_library(sublib1 SHARED "${CMAKE_BINARY_DIR}/sublib1.c")
+file(WRITE "${CMAKE_BINARY_DIR}/sublib2.c" "void sublib2(void)\n{\n}\n")
+add_library(sublib2 SHARED "${CMAKE_BINARY_DIR}/sublib2.c")
+target_link_libraries(toplib PRIVATE sublib1 sublib2)
+target_link_libraries(sublib1 PRIVATE sublib2)
+set_property(TARGET toplib PROPERTY INSTALL_RPATH "@loader_path/d1;@loader_path/d2")
+set_property(TARGET sublib1 PROPERTY INSTALL_RPATH "@loader_path/;@loader_path/../d2")
+install(TARGETS toplib DESTINATION lib)
+install(TARGETS sublib1 DESTINATION lib/d1)
+install(TARGETS sublib2 DESTINATION lib/d2)
+
+install(CODE [[
+ file(GET_RUNTIME_DEPENDENCIES
+ LIBRARIES
+ "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:toplib>"
+ RPATH_PREFIX _rpaths
+ )
+
+ set(_expected_rpath "(^|;)@loader_path/;@loader_path/\\.\\./d2$")
+ set(_actual_rpath "${_rpaths_${CMAKE_INSTALL_PREFIX}/lib/d1/$<TARGET_FILE_NAME:sublib1>}")
+ if(NOT _actual_rpath MATCHES "${_expected_rpath}")
+ message(FATAL_ERROR "Expected rpath:\n ${_expected_rpath}\nActual rpath:\n ${_actual_rpath}")
+ endif()
+
+ # Since RPATH_PREFIX is an undocumented option for install(), we don't really need the rpath
+ # for the top files anyway.
+ if(DEFINED "_rpaths_${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:toplib>")
+ message(FATAL_ERROR "rpath for top library should not be defined")
+ endif()
+ ]])
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-all-check.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-all-check.cmake
index f1d70a109..cb0e534a3 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-all-check.cmake
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-all-check.cmake
@@ -1,21 +1,3 @@
-function(check_contents filename contents_regex)
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
- file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
- if(NOT contents MATCHES "${contents_regex}")
- string(APPEND RunCMake_TEST_FAILED "File contents:
- ${contents}
-do not match what we expected:
- ${contents_regex}
-in file:
- ${CMAKE_INSTALL_PREFIX}/${filename}\n")
- set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
- endif()
- else()
- string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
- set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
- endif()
-endfunction()
-
set(_check
[=[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-build/root-all/bin/\.conflict/\.\./(lib)?libdir\.dll]=]
[=[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-build/root-all/bin/\.search/(lib)?search\.dll]=]
diff --git a/Tests/RunCMake/file-RPATH/Common.cmake b/Tests/RunCMake/file-RPATH/Common.cmake
index cc1efb533..7034aadb3 100644
--- a/Tests/RunCMake/file-RPATH/Common.cmake
+++ b/Tests/RunCMake/file-RPATH/Common.cmake
@@ -62,3 +62,40 @@ foreach(f ${files})
message(FATAL_ERROR "RPATH_CHECK did not remove ${f}")
endif()
endforeach()
+
+# TODO Implement RPATH_SET in XCOFF.
+if(format STREQUAL "ELF")
+ foreach(f ${names})
+ file(COPY ${in}/${f} DESTINATION ${out} NO_SOURCE_PERMISSIONS)
+ endforeach()
+
+ foreach(f ${files})
+ # Set the RPATH.
+ file(RPATH_SET FILE "${f}"
+ NEW_RPATH "/new/rpath")
+ set(rpath)
+ file(STRINGS "${f}" rpath REGEX "/new/rpath" LIMIT_COUNT 1)
+ if(NOT rpath)
+ message(FATAL_ERROR "RPATH not set in ${f}")
+ endif()
+ file(STRINGS "${f}" rpath REGEX "/rpath/sample" LIMIT_COUNT 1)
+ if(rpath)
+ message(FATAL_EROR "RPATH not removed in ${f}")
+ endif()
+
+ # Remove the RPATH.
+ file(RPATH_SET FILE "${f}"
+ NEW_RPATH "")
+ set(rpath)
+ file(STRINGS "${f}" rpath REGEX "/new/rpath" LIMIT_COUNT 1)
+ if(rpath)
+ message(FATAL_ERROR "RPATH not removed from ${f}")
+ endif()
+
+ # Check again...this should remove the file.
+ file(RPATH_CHECK FILE "${f}" RPATH "/new/rpath")
+ if(EXISTS "${f}")
+ message(FATAL_ERROR "RPATH_CHECK did not remove ${f}")
+ endif()
+ endforeach()
+endif()
diff --git a/Tests/RunCMake/file/COPY_FILE-arg-missing-result.txt b/Tests/RunCMake/file/COPY_FILE-arg-missing-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-arg-missing-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/COPY_FILE-arg-missing-stderr.txt b/Tests/RunCMake/file/COPY_FILE-arg-missing-stderr.txt
new file mode 100644
index 000000000..2ba38b66a
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-arg-missing-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/COPY_FILE-arg-missing.cmake:1 \(file\):
+ file COPY_FILE must be called with at least two additional arguments
diff --git a/Tests/RunCMake/file/COPY_FILE-arg-missing.cmake b/Tests/RunCMake/file/COPY_FILE-arg-missing.cmake
new file mode 100644
index 000000000..0e56c3894
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-arg-missing.cmake
@@ -0,0 +1 @@
+file(COPY_FILE "old")
diff --git a/Tests/RunCMake/file/COPY_FILE-arg-unknown-result.txt b/Tests/RunCMake/file/COPY_FILE-arg-unknown-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-arg-unknown-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/COPY_FILE-arg-unknown-stderr.txt b/Tests/RunCMake/file/COPY_FILE-arg-unknown-stderr.txt
new file mode 100644
index 000000000..e5ccd331c
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-arg-unknown-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake:1 \(file\):
+ file COPY_FILE unknown argument:
+
+ unknown$
diff --git a/Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake b/Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake
new file mode 100644
index 000000000..835f39e11
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake
@@ -0,0 +1 @@
+file(COPY_FILE "old" "new" unknown)
diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture-stdout.txt b/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture-stdout.txt
new file mode 100644
index 000000000..45b3d27ea
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture-stdout.txt
@@ -0,0 +1 @@
+^-- file\(COPY_FILE\) failed with result: cannot copy a directory
diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture.cmake b/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture.cmake
new file mode 100644
index 000000000..acec05ab3
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture.cmake
@@ -0,0 +1,8 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(MAKE_DIRECTORY "${oldname}")
+file(COPY_FILE "${oldname}" "${newname}" RESULT result)
+message(STATUS "file(COPY_FILE) failed with result: ${result}")
+if(EXISTS "${newname}")
+ message(FATAL_ERROR "The new name exists:\n ${newname}")
+endif()
diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-result.txt b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-stderr.txt b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-stderr.txt
new file mode 100644
index 000000000..2fe8bec56
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake:[0-9] \(file\):
+ file COPY_FILE cannot copy a directory
+
+ [^
+]*/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-build/input
diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake
new file mode 100644
index 000000000..a86ba8d39
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake
@@ -0,0 +1,4 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(MAKE_DIRECTORY "${oldname}")
+file(COPY_FILE "${oldname}" "${newname}")
diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture-stdout.txt b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture-stdout.txt
new file mode 100644
index 000000000..45b3d27ea
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture-stdout.txt
@@ -0,0 +1 @@
+^-- file\(COPY_FILE\) failed with result: cannot copy a directory
diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture.cmake b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture.cmake
new file mode 100644
index 000000000..acec05ab3
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture.cmake
@@ -0,0 +1,8 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(MAKE_DIRECTORY "${oldname}")
+file(COPY_FILE "${oldname}" "${newname}" RESULT result)
+message(STATUS "file(COPY_FILE) failed with result: ${result}")
+if(EXISTS "${newname}")
+ message(FATAL_ERROR "The new name exists:\n ${newname}")
+endif()
diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-result.txt b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-stderr.txt b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-stderr.txt
new file mode 100644
index 000000000..c58dc2c12
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake:[0-9] \(file\):
+ file COPY_FILE cannot copy a directory
+
+ [^
+]*/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-build/input
diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake
new file mode 100644
index 000000000..a86ba8d39
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake
@@ -0,0 +1,4 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(MAKE_DIRECTORY "${oldname}")
+file(COPY_FILE "${oldname}" "${newname}")
diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-capture.cmake b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-capture.cmake
new file mode 100644
index 000000000..028220e96
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-capture.cmake
@@ -0,0 +1,9 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+file(MAKE_DIRECTORY "${newname}")
+file(COPY_FILE "${oldname}" "${newname}" RESULT result ONLY_IF_DIFFERENT)
+message(STATUS "file(COPY_FILE) failed with result: ${result}")
+if(NOT EXISTS "${oldname}")
+ message(FATAL_ERROR "The old name still does not exist:\n ${oldname}")
+endif()
diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-result.txt b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-stderr.txt b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-stderr.txt
new file mode 100644
index 000000000..fd5ceeed9
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake:[0-9] \(file\):
+ file COPY_FILE cannot copy to a directory
+
+ [^
+]*/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-build/output
diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake
new file mode 100644
index 000000000..a56b4e75e
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake
@@ -0,0 +1,5 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+file(MAKE_DIRECTORY "${newname}")
+file(COPY_FILE "${oldname}" "${newname}" ONLY_IF_DIFFERENT)
diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite.cmake b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite.cmake
new file mode 100644
index 000000000..059a308ac
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite.cmake
@@ -0,0 +1,12 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+execute_process(COMMAND "${CMAKE_COMMAND} -E sleep 1")
+file(WRITE "${newname}" "")
+file(TIMESTAMP "${newname}" before_copy UTC)
+file(COPY_FILE "${oldname}" "${newname}" RESULT result ONLY_IF_DIFFERENT)
+file(TIMESTAMP "${newname}" after_copy UTC)
+if (NOT before_copy STREQUAL after_copy)
+ message(FATAL_ERROR
+ "${newname} was modified even though ONLY_IF_DIFFERENT was specified")
+endif ()
diff --git a/Tests/RunCMake/file/COPY_FILE-file-replace.cmake b/Tests/RunCMake/file/COPY_FILE-file-replace.cmake
new file mode 100644
index 000000000..40e42905a
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-replace.cmake
@@ -0,0 +1,9 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "a")
+file(WRITE "${newname}" "b")
+file(COPY_FILE "${oldname}" "${newname}")
+file(READ "${newname}" new)
+if(NOT "${new}" STREQUAL "a")
+ message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.")
+endif()
diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture-stdout.txt b/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture-stdout.txt
new file mode 100644
index 000000000..24f969f05
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture-stdout.txt
@@ -0,0 +1 @@
+^-- file\(COPY_FILE\) failed with result: cannot copy to a directory
diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture.cmake b/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture.cmake
new file mode 100644
index 000000000..98621c6e1
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture.cmake
@@ -0,0 +1,9 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+file(MAKE_DIRECTORY "${newname}")
+file(COPY_FILE "${oldname}" "${newname}" RESULT result)
+message(STATUS "file(COPY_FILE) failed with result: ${result}")
+if(NOT EXISTS "${oldname}")
+ message(FATAL_ERROR "The old name does not exist:\n ${oldname}")
+endif()
diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-result.txt b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-stderr.txt b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-stderr.txt
new file mode 100644
index 000000000..ba2a0276c
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake:[0-9] \(file\):
+ file COPY_FILE cannot copy to a directory
+
+ [^
+]*/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-build/output
diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake
new file mode 100644
index 000000000..c2628dd3e
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake
@@ -0,0 +1,5 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+file(MAKE_DIRECTORY "${newname}")
+file(COPY_FILE "${oldname}" "${newname}")
diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-file.cmake b/Tests/RunCMake/file/COPY_FILE-file-to-file.cmake
new file mode 100644
index 000000000..26b702a8a
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-to-file.cmake
@@ -0,0 +1,10 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+file(COPY_FILE "${oldname}" "${newname}")
+if(NOT EXISTS "${oldname}")
+ message(FATAL_ERROR "The old name does not exist:\n ${oldname}")
+endif()
+if(NOT EXISTS "${newname}")
+ message(FATAL_ERROR "The new name does not exist:\n ${newname}")
+endif()
diff --git a/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake b/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake
new file mode 100644
index 000000000..93a02043e
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake
@@ -0,0 +1,10 @@
+set(lnkname "${CMAKE_CURRENT_BINARY_DIR}/link")
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${lnkname}" "a")
+file(CREATE_LINK "${lnkname}" "${oldname}")
+file(COPY_FILE "${oldname}" "${newname}")
+file(READ "${newname}" new)
+if(NOT "${new}" STREQUAL "a")
+ message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.")
+endif()
diff --git a/Tests/RunCMake/file/REAL_PATH.cmake b/Tests/RunCMake/file/REAL_PATH.cmake
index be25706b2..0b5d3c0fd 100644
--- a/Tests/RunCMake/file/REAL_PATH.cmake
+++ b/Tests/RunCMake/file/REAL_PATH.cmake
@@ -1,14 +1,36 @@
-file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/test.txt")
-file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/test.sym")
-file(CREATE_LINK "test.txt" "${CMAKE_CURRENT_BINARY_DIR}/test.sym" SYMBOLIC)
+if (NOT WIN32 OR CYGWIN)
+ file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/test.txt")
+ file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/test.sym")
+ file(CREATE_LINK "test.txt" "${CMAKE_CURRENT_BINARY_DIR}/test.sym" SYMBOLIC)
-file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/test.sym" real_path)
-if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt")
- message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"")
+ file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/test.sym" real_path)
+ if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt")
+ message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"")
+ endif()
+
+ file(REAL_PATH "test.sym" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+ if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt")
+ message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"")
+ endif()
+endif()
+
+
+If (WIN32)
+ cmake_path(SET HOME_DIR "$ENV{USERPROFILE}")
+ if (NOT HOME_DIR)
+ cmake_path(SET HOME_DIR "$ENV{HOME}")
+ endif()
+else()
+ set(HOME_DIR "$ENV{HOME}")
+endif()
+
+file(REAL_PATH "~" real_path EXPAND_TILDE)
+if (NOT real_path STREQUAL "${HOME_DIR}")
+ message(SEND_ERROR "real path is \"${real_path}\", should be \"${HOME_DIR}\"")
endif()
-file(REAL_PATH "test.sym" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
-if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt")
- message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"")
+file(REAL_PATH "~/test.txt" real_path EXPAND_TILDE)
+if (NOT real_path STREQUAL "${HOME_DIR}/test.txt")
+ message(SEND_ERROR "real path is \"${real_path}\", should be \"${HOME_DIR}/test.txt\"")
endif()
diff --git a/Tests/RunCMake/file/RENAME-arg-missing-result.txt b/Tests/RunCMake/file/RENAME-arg-missing-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-arg-missing-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/RENAME-arg-missing-stderr.txt b/Tests/RunCMake/file/RENAME-arg-missing-stderr.txt
new file mode 100644
index 000000000..98d29614f
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-arg-missing-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/RENAME-arg-missing.cmake:1 \(file\):
+ file RENAME must be called with at least two additional arguments$
diff --git a/Tests/RunCMake/file/RENAME-arg-missing.cmake b/Tests/RunCMake/file/RENAME-arg-missing.cmake
new file mode 100644
index 000000000..2358ce982
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-arg-missing.cmake
@@ -0,0 +1 @@
+file(RENAME "old")
diff --git a/Tests/RunCMake/file/RENAME-arg-unknown-result.txt b/Tests/RunCMake/file/RENAME-arg-unknown-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-arg-unknown-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt b/Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt
new file mode 100644
index 000000000..16edb2576
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/RENAME-arg-unknown.cmake:1 \(file\):
+ file RENAME unknown argument:
+
+ unknown$
diff --git a/Tests/RunCMake/file/RENAME-arg-unknown.cmake b/Tests/RunCMake/file/RENAME-arg-unknown.cmake
new file mode 100644
index 000000000..3110f7047
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-arg-unknown.cmake
@@ -0,0 +1 @@
+file(RENAME "old" "new" unknown)
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt
new file mode 100644
index 000000000..a11633095
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt
@@ -0,0 +1 @@
+^-- file\(RENAME\) failed with result: NO_REPLACE$
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake
new file mode 100644
index 000000000..1ff41786f
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake
@@ -0,0 +1,9 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "a")
+file(WRITE "${newname}" "b")
+file(RENAME "${oldname}" "${newname}" NO_REPLACE RESULT result)
+message(STATUS "file(RENAME) failed with result: ${result}")
+if(NOT EXISTS "${oldname}")
+ message(FATAL_ERROR "The old name does not still exist:\n ${oldname}")
+endif()
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt
new file mode 100644
index 000000000..dd7294cd5
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt
@@ -0,0 +1,13 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake:[0-9] \(file\):
+ file RENAME failed to rename
+
+ [^
+]*/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-build/input
+
+ to
+
+ [^
+]*/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-build/output
+
+ because: path not replaced$
diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake
new file mode 100644
index 000000000..c05dd6359
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake
@@ -0,0 +1,5 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "a")
+file(WRITE "${newname}" "b")
+file(RENAME "${oldname}" "${newname}" NO_REPLACE)
diff --git a/Tests/RunCMake/file/RENAME-file-replace.cmake b/Tests/RunCMake/file/RENAME-file-replace.cmake
new file mode 100644
index 000000000..efbfaed11
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-replace.cmake
@@ -0,0 +1,9 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "a")
+file(WRITE "${newname}" "b")
+file(RENAME "${oldname}" "${newname}")
+file(READ "${newname}" new)
+if(NOT "${new}" STREQUAL "a")
+ message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.")
+endif()
diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt b/Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt
new file mode 100644
index 000000000..0276a5f89
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt
@@ -0,0 +1 @@
+^-- file\(RENAME\) failed with result: [A-Za-z]
diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake b/Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake
new file mode 100644
index 000000000..4f817e8a6
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake
@@ -0,0 +1,9 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+file(MAKE_DIRECTORY "${newname}")
+file(RENAME "${oldname}" "${newname}" RESULT result)
+message(STATUS "file(RENAME) failed with result: ${result}")
+if(NOT EXISTS "${oldname}")
+ message(FATAL_ERROR "The old name does not still exist:\n ${oldname}")
+endif()
diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt b/Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt b/Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt
new file mode 100644
index 000000000..e4dbc38e9
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt
@@ -0,0 +1,13 @@
+^CMake Error at [^
+]*/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake:[0-9] \(file\):
+ file RENAME failed to rename
+
+ [^
+]*/Tests/RunCMake/file/RENAME-file-to-dir-fail-build/input
+
+ to
+
+ [^
+]*/Tests/RunCMake/file/RENAME-file-to-dir-fail-build/output
+
+ because: [A-Za-z]
diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake b/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake
new file mode 100644
index 000000000..61fa64463
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake
@@ -0,0 +1,5 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+file(MAKE_DIRECTORY "${newname}")
+file(RENAME "${oldname}" "${newname}")
diff --git a/Tests/RunCMake/file/RENAME-file-to-file.cmake b/Tests/RunCMake/file/RENAME-file-to-file.cmake
new file mode 100644
index 000000000..dbc411be1
--- /dev/null
+++ b/Tests/RunCMake/file/RENAME-file-to-file.cmake
@@ -0,0 +1,10 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+file(RENAME "${oldname}" "${newname}")
+if(EXISTS "${oldname}")
+ message(FATAL_ERROR "The old name still exists:\n ${oldname}")
+endif()
+if(NOT EXISTS "${newname}")
+ message(FATAL_ERROR "The new name does not exist:\n ${newname}")
+endif()
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index 22813eb16..9efd3f493 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -50,6 +50,30 @@ run_cmake(SIZE-error-does-not-exist)
run_cmake(REMOVE-empty)
+run_cmake_script(COPY_FILE-file-replace)
+run_cmake_script(COPY_FILE-dir-to-file-capture)
+run_cmake_script(COPY_FILE-dir-to-file-fail)
+run_cmake_script(COPY_FILE-dirlink-to-file-capture)
+run_cmake_script(COPY_FILE-dirlink-to-file-fail)
+run_cmake_script(COPY_FILE-file-to-file)
+run_cmake_script(COPY_FILE-file-to-dir-capture)
+run_cmake_script(COPY_FILE-file-to-dir-fail)
+run_cmake_script(COPY_FILE-file-ONLY_IF_DIFFERENT-capture)
+run_cmake_script(COPY_FILE-file-ONLY_IF_DIFFERENT-fail)
+run_cmake_script(COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite)
+run_cmake_script(COPY_FILE-link-to-file)
+run_cmake_script(COPY_FILE-arg-missing)
+run_cmake_script(COPY_FILE-arg-unknown)
+
+run_cmake_script(RENAME-file-replace)
+run_cmake_script(RENAME-file-to-file)
+run_cmake_script(RENAME-file-to-dir-capture)
+run_cmake_script(RENAME-file-to-dir-fail)
+run_cmake_script(RENAME-file-NO_REPLACE-capture)
+run_cmake_script(RENAME-file-NO_REPLACE-fail)
+run_cmake_script(RENAME-arg-missing)
+run_cmake_script(RENAME-arg-unknown)
+
# tests are valid both for GLOB and GLOB_RECURSE
run_cmake(GLOB-sort-dedup)
run_cmake(GLOB-error-LIST_DIRECTORIES-not-boolean)
@@ -63,7 +87,9 @@ run_cmake(GLOB-noexp-RELATIVE)
run_cmake_command(GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE ${CMAKE_COMMAND} -P
${RunCMake_SOURCE_DIR}/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE.cmake)
-if(NOT WIN32 OR CYGWIN)
+if(NOT WIN32
+ AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS
+ )
run_cmake(CREATE_LINK-SYMBOLIC)
run_cmake(CREATE_LINK-SYMBOLIC-noexist)
run_cmake(GLOB_RECURSE-cyclic-recursion)
@@ -72,11 +98,12 @@ if(NOT WIN32 OR CYGWIN)
run_cmake(READ_SYMLINK-noexist)
run_cmake(READ_SYMLINK-notsymlink)
run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN)
- run_cmake(REAL_PATH-unexpected-arg)
- run_cmake(REAL_PATH-no-base-dir)
- run_cmake(REAL_PATH)
endif()
+run_cmake(REAL_PATH-unexpected-arg)
+run_cmake(REAL_PATH-no-base-dir)
+run_cmake(REAL_PATH)
+
if(RunCMake_GENERATOR MATCHES "Ninja")
# Detect ninja version so we know what tests can be supported.
execute_process(
@@ -137,7 +164,9 @@ else()
run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second ${CMAKE_COMMAND} --build .)
run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-nowork ${CMAKE_COMMAND} --build .)
- if(NOT WIN32 OR CYGWIN)
+ if(NOT WIN32
+ AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS
+ )
message(STATUS "GLOB-CONFIGURE_DEPENDS-CMP0009-RerunCMake: link the first test directory into a new directory...")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/test2")
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${RunCMake_TEST_BINARY_DIR}/test" "${RunCMake_TEST_BINARY_DIR}/test2/test_folder_symlink")
diff --git a/Tests/RunCMake/find_file/FromPATHEnv-stdout-msys.txt b/Tests/RunCMake/find_file/FromPATHEnv-stdout-msys.txt
new file mode 100644
index 000000000..6912bdfac
--- /dev/null
+++ b/Tests/RunCMake/find_file/FromPATHEnv-stdout-msys.txt
@@ -0,0 +1,9 @@
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
diff --git a/Tests/RunCMake/find_file/NO_CACHE-stdout.txt b/Tests/RunCMake/find_file/NO_CACHE-stdout.txt
new file mode 100644
index 000000000..e78632112
--- /dev/null
+++ b/Tests/RunCMake/find_file/NO_CACHE-stdout.txt
@@ -0,0 +1,18 @@
+-- FILE_exists='.+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- FILE_doNotExists='FILE_doNotExists-NOTFOUND'
+--[ ]+
+-- Policy CMP0125 = OLD
+-- CACHED FILE_cache='unknown'
+-- FILE_cache='unknown'
+-- CACHED FILE_cache='PrefixInPATH.h'
+-- FILE_cache='PrefixInPATH.h'
+-- CACHED FILE_cache='PrefixInPATH.h'
+-- FILE_cache='PrefixInPATH.h'
+--[ ]+
+-- Policy CMP0125 = NEW
+-- CACHED FILE_cache='unknown'
+-- FILE_cache='unknown'
+-- CACHED FILE_cache='PrefixInPATH.h'
+-- FILE_cache='PrefixInPATH.h'
+-- CACHED FILE_cache='PrefixInPATH.h'
+-- FILE_cache='.+/Tests/RunCMake/find_file/NO_CACHE-build/PrefixInPATH.h'
diff --git a/Tests/RunCMake/find_file/NO_CACHE.cmake b/Tests/RunCMake/find_file/NO_CACHE.cmake
new file mode 100644
index 000000000..65156b958
--- /dev/null
+++ b/Tests/RunCMake/find_file/NO_CACHE.cmake
@@ -0,0 +1,129 @@
+find_file(FILE_exists
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (DEFINED CACHE{FILE_exists})
+ message(SEND_ERROR "Cache variable defined: FILE_exists")
+endif()
+message(STATUS "FILE_exists='${FILE_exists}'")
+
+
+find_file(FILE_doNotExists
+ NAMES doNotExists.h
+ NO_CACHE
+ )
+if (DEFINED CACHE{FILE_doNotExists})
+ message(SEND_ERROR "Cache variable defined: FILE_doNotExists")
+endif()
+message(STATUS "FILE_doNotExists='${FILE_doNotExists}'")
+
+
+cmake_policy(SET CMP0125 OLD)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = OLD")
+file(REMOVE "${CMAKE_BINARY_DIR}/PrefixInPATH.h")
+
+set(FILE_cache "unknown" CACHE FILEPATH "")
+find_file(FILE_cache
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{FILE_cache})
+ message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "")
+unset(FILE_cache)
+find_file(FILE_cache
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{FILE_cache})
+ message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "")
+unset(FILE_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE FILE_cache PROPERTY TYPE UNINITIALIZED)
+find_file(FILE_cache
+ NAMES PrefixInPATH.h
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{FILE_cache})
+ message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+cmake_policy(SET CMP0125 NEW)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = NEW")
+file(REMOVE "${CMAKE_BINARY_DIR}/PrefixInPATH.h")
+
+set(FILE_cache "unknown" CACHE FILEPATH "")
+unset(FILE_cache)
+find_file(FILE_cache
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{FILE_cache})
+ message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "")
+unset(FILE_cache)
+find_file(FILE_cache
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{FILE_cache})
+ message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "")
+unset(FILE_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE FILE_cache PROPERTY TYPE UNINITIALIZED)
+find_file(FILE_cache
+ NAMES PrefixInPATH.h
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{FILE_cache})
+ message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
diff --git a/Tests/RunCMake/find_file/PrefixInPATH-stdout-msys.txt b/Tests/RunCMake/find_file/PrefixInPATH-stdout-msys.txt
new file mode 100644
index 000000000..d73bc1dfd
--- /dev/null
+++ b/Tests/RunCMake/find_file/PrefixInPATH-stdout-msys.txt
@@ -0,0 +1,4 @@
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake
index 93dfb7870..95f55a5b3 100644
--- a/Tests/RunCMake/find_file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake
@@ -4,3 +4,4 @@ run_cmake(FromPATHEnv)
run_cmake(FromPrefixPath)
run_cmake(PrefixInPATH)
run_cmake(Required)
+run_cmake(NO_CACHE)
diff --git a/Tests/RunCMake/find_library/FromPATHEnv-stdout-msys.txt b/Tests/RunCMake/find_library/FromPATHEnv-stdout-msys.txt
new file mode 100644
index 000000000..01e272050
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromPATHEnv-stdout-msys.txt
@@ -0,0 +1,6 @@
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/NO_CACHE-stdout.txt b/Tests/RunCMake/find_library/NO_CACHE-stdout.txt
new file mode 100644
index 000000000..1b4c2a90d
--- /dev/null
+++ b/Tests/RunCMake/find_library/NO_CACHE-stdout.txt
@@ -0,0 +1,18 @@
+-- LIB_exists='.+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- LIB_doNotExists='LIB_doNotExists-NOTFOUND'
+--[ ]+
+-- Policy CMP0125 = OLD
+-- CACHED LIB_cache='unknown'
+-- LIB_cache='unknown'
+-- CACHED LIB_cache='libPrefixInPATH.a'
+-- LIB_cache='libPrefixInPATH.a'
+-- CACHED LIB_cache='libPrefixInPATH.a'
+-- LIB_cache='libPrefixInPATH.a'
+--[ ]+
+-- Policy CMP0125 = NEW
+-- CACHED LIB_cache='unknown'
+-- LIB_cache='unknown'
+-- CACHED LIB_cache='libPrefixInPATH.a'
+-- LIB_cache='libPrefixInPATH.a'
+-- CACHED LIB_cache='libPrefixInPATH.a'
+-- LIB_cache='.+/Tests/RunCMake/find_library/NO_CACHE-build/libPrefixInPATH.a'
diff --git a/Tests/RunCMake/find_library/NO_CACHE.cmake b/Tests/RunCMake/find_library/NO_CACHE.cmake
new file mode 100644
index 000000000..a94b8284c
--- /dev/null
+++ b/Tests/RunCMake/find_library/NO_CACHE.cmake
@@ -0,0 +1,133 @@
+list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib)
+list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a)
+
+find_library(LIB_exists
+ NAMES PrefixInPATH
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (DEFINED CACHE{LIB_exists})
+ message(SEND_ERROR "Cache variable defined: LIB_exists")
+endif()
+message(STATUS "LIB_exists='${LIB_exists}'")
+
+
+find_library(LIB_doNotExists
+ NAMES doNotExists
+ NO_CACHE
+ )
+if (DEFINED CACHE{LIB_doNotExists})
+ message(SEND_ERROR "Cache variable defined: LIB_doNotExists")
+endif()
+message(STATUS "LIB_doNotExists='${LIB_doNotExists}'")
+
+
+cmake_policy(SET CMP0125 OLD)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = OLD")
+file(REMOVE "${CMAKE_BINARY_DIR}/libPrefixInPATH.a")
+
+set(LIB_cache "unknown" CACHE FILEPATH "")
+find_library(LIB_cache
+ NAMES PrefixInPATH
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{LIB_cache})
+ message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "")
+unset(LIB_cache)
+find_library(LIB_cache
+ NAMES PrefixInPATH
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{LIB_cache})
+ message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "")
+unset(LIB_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/libPrefixInPATH.a" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE LIB_cache PROPERTY TYPE UNINITIALIZED)
+find_library(LIB_cache
+ NAMES PrefixInPATH
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{LIB_cache})
+ message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+cmake_policy(SET CMP0125 NEW)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = NEW")
+file(REMOVE "${CMAKE_BINARY_DIR}/libPrefixInPATH.a")
+
+set(LIB_cache "unknown" CACHE FILEPATH "")
+find_library(LIB_cache
+ NAMES PrefixInPATH
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{LIB_cache})
+ message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "")
+unset(LIB_cache)
+find_library(LIB_cache
+ NAMES PrefixInPATH
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{LIB_cache})
+ message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "")
+unset(LIB_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/libPrefixInPATH.a" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE LIB_cache PROPERTY TYPE UNINITIALIZED)
+find_library(LIB_cache
+ NAMES PrefixInPATH
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{LIB_cache})
+ message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
diff --git a/Tests/RunCMake/find_library/PrefixInPATH-stdout-msys.txt b/Tests/RunCMake/find_library/PrefixInPATH-stdout-msys.txt
new file mode 100644
index 000000000..1ab884cb7
--- /dev/null
+++ b/Tests/RunCMake/find_library/PrefixInPATH-stdout-msys.txt
@@ -0,0 +1,4 @@
+-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND'
+-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake
index c7d69e401..e2971733b 100644
--- a/Tests/RunCMake/find_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake
@@ -9,3 +9,4 @@ if(UNIX AND NOT CYGWIN)
endif()
run_cmake(PrefixInPATH)
run_cmake(Required)
+run_cmake(NO_CACHE)
diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake
index a899f46ad..3ba04c8bd 100644
--- a/Tests/RunCMake/find_package/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake
@@ -38,8 +38,11 @@ run_cmake(VersionRange3)
run_cmake(VersionRange4)
run_cmake(VersionRangeConfig)
run_cmake(VersionRangeConfig2)
+run_cmake(VersionRangeConfig02)
run_cmake(VersionRangeConfigStd)
run_cmake(VersionRangeConfigStd2)
-if(UNIX)
+if(UNIX
+ AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS
+ )
run_cmake(SetFoundResolved)
endif()
diff --git a/Tests/RunCMake/find_package/VersionRangeCfg/VersionRangeCfgConfigVersion.cmake b/Tests/RunCMake/find_package/VersionRangeCfg/VersionRangeCfgConfigVersion.cmake
index e9f607685..1d0adfe3f 100644
--- a/Tests/RunCMake/find_package/VersionRangeCfg/VersionRangeCfgConfigVersion.cmake
+++ b/Tests/RunCMake/find_package/VersionRangeCfg/VersionRangeCfgConfigVersion.cmake
@@ -1,6 +1,7 @@
if (NOT PACKAGE_FIND_VERSION_COMPLETE STREQUAL "1.2.3.4...5.6.7.8"
- AND NOT PACKAGE_FIND_VERSION_COMPLETE STREQUAL "1.2.3.4...<5.6.7.8")
+ AND NOT PACKAGE_FIND_VERSION_COMPLETE STREQUAL "1.2.3.4...<5.6.7.8"
+ AND NOT PACKAGE_FIND_VERSION_COMPLETE STREQUAL "1.02.03.04...<5.06.07.08")
message (SEND_ERROR "Wrong value for PACKAGE_FIND_VERSION_COMPLETE: ${PACKAGE_FIND_VERSION_COMPLETE}")
endif()
@@ -21,7 +22,8 @@ if (NOT PACKAGE_FIND_VERSION_TWEAK VERSION_EQUAL "4")
endif()
if (NOT PACKAGE_FIND_VERSION_RANGE STREQUAL "1.2.3.4...5.6.7.8"
- AND NOT PACKAGE_FIND_VERSION_RANGE STREQUAL "1.2.3.4...<5.6.7.8")
+ AND NOT PACKAGE_FIND_VERSION_RANGE STREQUAL "1.2.3.4...<5.6.7.8"
+ AND NOT PACKAGE_FIND_VERSION_RANGE STREQUAL "1.02.03.04...<5.06.07.08")
message (SEND_ERROR "Wrong value for PACKAGE_FIND_VERSION_RANGE: ${PACKAGE_FIND_VERSION_RANGE}")
endif()
diff --git a/Tests/RunCMake/find_package/VersionRangeConfig02.cmake b/Tests/RunCMake/find_package/VersionRangeConfig02.cmake
new file mode 100644
index 000000000..6522f6de9
--- /dev/null
+++ b/Tests/RunCMake/find_package/VersionRangeConfig02.cmake
@@ -0,0 +1,23 @@
+set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR})
+
+find_package(VersionRange 1.02.03.04...<5.06.07.08 CONFIG NAMES VersionRangeCfg)
+
+if (NOT VersionRange_FOUND)
+ message (FATAL_ERROR "Package VersionRange not found in CONFIG mode.")
+endif()
+
+if (NOT VersionRange_VERSION VERSION_EQUAL "2.3.4.5")
+ message (SEND_ERROR "Wrong version : ${VersionRange_VERSION}")
+endif()
+if (NOT VersionRange_VERSION_MAJOR VERSION_EQUAL "2")
+ message (SEND_ERROR "Wrong major version : ${VersionRange_VERSION_MAJOR}")
+endif()
+if (NOT VersionRange_VERSION_MINOR VERSION_EQUAL "3")
+ message (SEND_ERROR "Wrong minor version : ${VersionRange_VERSION_MINOR}")
+endif()
+if (NOT VersionRange_VERSION_PATCH VERSION_EQUAL "4")
+ message (SEND_ERROR "Wrong patch version : ${VersionRange_VERSION_PATCH}")
+endif()
+if (NOT VersionRange_VERSION_TWEAK VERSION_EQUAL "5")
+ message (SEND_ERROR "Wrong tweak version : ${VersionRange_VERSION_TWEAK}")
+endif()
diff --git a/Tests/RunCMake/find_path/FromPATHEnv-stdout-msys.txt b/Tests/RunCMake/find_path/FromPATHEnv-stdout-msys.txt
new file mode 100644
index 000000000..8f3e7ca5f
--- /dev/null
+++ b/Tests/RunCMake/find_path/FromPATHEnv-stdout-msys.txt
@@ -0,0 +1,9 @@
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include'
+-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
diff --git a/Tests/RunCMake/find_path/NO_CACHE-stdout.txt b/Tests/RunCMake/find_path/NO_CACHE-stdout.txt
new file mode 100644
index 000000000..a41454ef3
--- /dev/null
+++ b/Tests/RunCMake/find_path/NO_CACHE-stdout.txt
@@ -0,0 +1,18 @@
+-- PATH_exists='.+/Tests/RunCMake/find_path/include/'
+-- PATH_exists='PATH_doNotExists-NOTFOUND'
+--[ ]+
+-- Policy CMP0125 = OLD
+-- CACHED PATH_cache='unknown'
+-- PATH_cache='unknown'
+-- CACHED PATH_cache='include'
+-- PATH_cache='include'
+-- CACHED PATH_cache='include'
+-- PATH_cache='include'
+--[ ]+
+-- Policy CMP0125 = NEW
+-- CACHED PATH_cache='unknown'
+-- PATH_cache='unknown'
+-- CACHED PATH_cache='include'
+-- PATH_cache='include'
+-- CACHED PATH_cache='include'
+-- PATH_cache='.+/Tests/RunCMake/find_path/NO_CACHE-build/include'
diff --git a/Tests/RunCMake/find_path/NO_CACHE.cmake b/Tests/RunCMake/find_path/NO_CACHE.cmake
new file mode 100644
index 000000000..4779ac8a7
--- /dev/null
+++ b/Tests/RunCMake/find_path/NO_CACHE.cmake
@@ -0,0 +1,131 @@
+find_path(PATH_exists
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (DEFINED CACHE{PATH_exists})
+ message(SEND_ERROR "Cache variable defined: PATH_exists")
+endif()
+message(STATUS "PATH_exists='${PATH_exists}'")
+
+
+find_path(PATH_doNotExists
+ NAMES doNotExists.h
+ NO_CACHE
+ )
+if (DEFINED CACHE{PATH_doNotExists})
+ message(SEND_ERROR "Cache variable defined: PATH_doNotExists")
+endif()
+message(STATUS "PATH_exists='${PATH_doNotExists}'")
+
+
+cmake_policy(SET CMP0125 OLD)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = OLD")
+file(REMOVE "${CMAKE_BINARY_DIR}/PrefixInPATH.h")
+
+set(PATH_cache "unknown" CACHE PATH "")
+find_path(PATH_cache
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PATH_cache})
+ message(SEND_ERROR "Cache variable defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+set(PATH_cache "include" CACHE PATH "")
+unset(PATH_cache)
+find_path(PATH_cache
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PATH_cache})
+ message(SEND_ERROR "Cache variable defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+set(PATH_cache "include" CACHE PATH "")
+unset(PATH_cache)
+# simulate cache variable defined in command line
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include")
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}/include")
+set_property(CACHE PATH_cache PROPERTY TYPE UNINITIALIZED)
+find_path(PATH_cache
+ NAMES PrefixInPATH.h
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PATH_cache})
+ message(SEND_ERROR "Cache variable not defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+cmake_policy(SET CMP0125 NEW)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = NEW")
+file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/include")
+
+set(PATH_cache "unknown" CACHE PATH "")
+unset(PATH_cache)
+find_path(PATH_cache
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PATH_cache})
+ message(SEND_ERROR "Cache variable defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+set(PATH_cache "include" CACHE PATH "")
+unset(PATH_cache)
+find_path(PATH_cache
+ NAMES PrefixInPATH.h
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PATH_cache})
+ message(SEND_ERROR "Cache variable defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+set(PATH_cache "include" CACHE PATH "")
+unset(PATH_cache)
+# simulate cache variable defined in command line
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include")
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}/include")
+set_property(CACHE PATH_cache PROPERTY TYPE UNINITIALIZED)
+find_path(PATH_cache
+ NAMES PrefixInPATH.h
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PATH_cache})
+ message(SEND_ERROR "Cache variable not defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
diff --git a/Tests/RunCMake/find_path/PrefixInPATH-stdout-msys.txt b/Tests/RunCMake/find_path/PrefixInPATH-stdout-msys.txt
new file mode 100644
index 000000000..bb2ceb725
--- /dev/null
+++ b/Tests/RunCMake/find_path/PrefixInPATH-stdout-msys.txt
@@ -0,0 +1,4 @@
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake
index 5c919bb66..90ee768cb 100644
--- a/Tests/RunCMake/find_path/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake
@@ -4,6 +4,7 @@ run_cmake(EmptyOldStyle)
run_cmake(FromPATHEnv)
run_cmake(PrefixInPATH)
run_cmake(Required)
+run_cmake(NO_CACHE)
if(APPLE)
run_cmake(FrameworksWithSubdirs)
diff --git a/Tests/RunCMake/find_program/NO_CACHE-stdout.txt b/Tests/RunCMake/find_program/NO_CACHE-stdout.txt
new file mode 100644
index 000000000..c235d8143
--- /dev/null
+++ b/Tests/RunCMake/find_program/NO_CACHE-stdout.txt
@@ -0,0 +1,18 @@
+-- PROG_A='.+/Tests/RunCMake/find_program/A/testA'
+-- PROG_AandB='PROG_AandB-NOTFOUND'
+--[ ]+
+-- Policy CMP0125 = OLD
+-- CACHED PROG_cache='unknown'
+-- PROG_cache='unknown'
+-- CACHED PROG_cache='testA'
+-- PROG_cache='testA'
+-- CACHED PROG_cache='testA'
+-- PROG_cache='testA'
+--[ ]+
+-- Policy CMP0125 = NEW
+-- CACHED PROG_cache='unknown'
+-- PROG_cache='unknown'
+-- CACHED PROG_cache='testA'
+-- PROG_cache='testA'
+-- CACHED PROG_cache='testA'
+-- PROG_cache='.+/Tests/RunCMake/find_program/NO_CACHE-build/testA'
diff --git a/Tests/RunCMake/find_program/NO_CACHE.cmake b/Tests/RunCMake/find_program/NO_CACHE.cmake
new file mode 100644
index 000000000..77a058260
--- /dev/null
+++ b/Tests/RunCMake/find_program/NO_CACHE.cmake
@@ -0,0 +1,130 @@
+find_program(PROG_A
+ NAMES testA
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (DEFINED CACHE{PROG_A})
+ message(SEND_ERROR "Cache variable defined: PROG_A")
+endif()
+message(STATUS "PROG_A='${PROG_A}'")
+
+
+find_program(PROG_AandB
+ NAMES testAandB
+ NO_CACHE
+ )
+if (DEFINED CACHE{PROG_AandB})
+ message(SEND_ERROR "Cache variable defined: PROG_AandN")
+endif()
+message(STATUS "PROG_AandB='${PROG_AandB}'")
+
+
+cmake_policy(SET CMP0125 OLD)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = OLD")
+file(REMOVE "${CMAKE_BINARY_DIR}/testA")
+
+set(PROG_cache "unknown" CACHE FILEPATH "")
+find_program(PROG_cache
+ NAMES testA
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PROG_cache})
+ message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+set(PROG_cache "testA" CACHE FILEPATH "")
+unset(PROG_cache)
+find_program(PROG_cache
+ NAMES testA
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PROG_cache})
+ message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+set(PROG_cache "testA" CACHE FILEPATH "")
+unset(PROG_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/A/testA" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE PROG_cache PROPERTY TYPE UNINITIALIZED)
+find_program(PROG_cache
+ NAMES testA
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PROG_cache})
+ message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+cmake_policy(SET CMP0125 NEW)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = NEW")
+file(REMOVE "${CMAKE_BINARY_DIR}/testA")
+
+set(PROG_cache "unknown" CACHE FILEPATH "")
+find_program(PROG_cache
+ NAMES testA
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PROG_cache})
+ message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+set(PROG_cache "testA" CACHE FILEPATH "")
+unset(PROG_cache)
+find_program(PROG_cache
+ NAMES testA
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PROG_cache})
+ message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+set(PROG_cache "testA" CACHE FILEPATH "")
+unset(PROG_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/A/testA" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE PROG_cache PROPERTY TYPE UNINITIALIZED)
+find_program(PROG_cache
+ NAMES testA
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ NO_CACHE
+ NO_DEFAULT_PATH
+ )
+if (NOT DEFINED CACHE{PROG_cache})
+ message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake
index 3e2392031..34edc19d5 100644
--- a/Tests/RunCMake/find_program/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake
@@ -5,8 +5,9 @@ run_cmake(DirsPerName)
run_cmake(NamesPerDir)
run_cmake(RelAndAbsPath)
run_cmake(Required)
+run_cmake(NO_CACHE)
-if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN)$")
+if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$")
run_cmake(WindowsCom)
run_cmake(WindowsExe)
else()
diff --git a/Tests/RunCMake/foreach/RunCMakeTest.cmake b/Tests/RunCMake/foreach/RunCMakeTest.cmake
index d3f7c231c..15ca47704 100644
--- a/Tests/RunCMake/foreach/RunCMakeTest.cmake
+++ b/Tests/RunCMake/foreach/RunCMakeTest.cmake
@@ -20,3 +20,5 @@ run_cmake(foreach-RANGE-non-int-test-3-2)
run_cmake(foreach-RANGE-non-int-test-3-3)
run_cmake(foreach-RANGE-invalid-test)
run_cmake(foreach-RANGE-out-of-range-test)
+run_cmake(foreach-var-scope-CMP0124-OLD)
+run_cmake(foreach-var-scope-CMP0124-NEW)
diff --git a/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake
new file mode 100644
index 000000000..7e2eee0fa
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake
@@ -0,0 +1,51 @@
+
+cmake_policy(SET CMP0124 NEW)
+
+foreach(VAR a b c)
+endforeach()
+if (DEFINED VAR)
+ message(SEND_ERROR "Variable 'VAR' unexpectedly defined.")
+endif()
+
+set(LIST1 a b c)
+set(LIST2 x y z)
+foreach(VAR1_1 VAR1_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+if (DEFINED VAR1_1 OR DEFINED VAR1_2)
+ message(SEND_ERROR "Variables 'VAR1_1' or 'VAR1_2' unexpectedly defined.")
+endif()
+
+
+set (VAR2 OLD)
+foreach(VAR2 a b c)
+endforeach()
+if (NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR2' not defined or wrong value.")
+endif()
+
+set (VAR2_2 OLD)
+foreach(VAR2_1 VAR2_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+if (DEFINED VAR2_1 OR NOT DEFINED VAR2_2)
+ message(SEND_ERROR "Variable 'VAR2_1' unexpectedly defined or variable 'VAR2_2' not defined.")
+endif()
+
+
+set (VAR3 OLD CACHE STRING "")
+foreach(VAR3 a b c)
+endforeach()
+# check that only cache variable is defined
+set(OLD_VALUE "${VAR3}")
+unset(VAR3 CACHE)
+if (DEFINED VAR3 OR NOT OLD_VALUE STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR3' wrongly defined or wrong value.")
+endif()
+
+set (VAR3_2 OLD CACHE STRING "")
+foreach(VAR3_1 VAR3_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+set(OLD_VALUE "${VAR3_2}")
+unset(VAR3_2 CACHE)
+if (DEFINED VAR3_1 OR DEFINED VAR3_2 OR NOT OLD_VALUE STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR3_1' unexpectedly defined or variable 'VAR2_2' wrongly defined or wrong value.")
+endif()
diff --git a/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake
new file mode 100644
index 000000000..f95598215
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake
@@ -0,0 +1,53 @@
+
+cmake_policy(SET CMP0124 OLD)
+
+foreach(VAR a b c)
+endforeach()
+if (NOT DEFINED VAR OR NOT VAR STREQUAL "")
+ message(SEND_ERROR "Variable 'VAR' not defined or wrong value.")
+endif()
+
+set(LIST1 a b c)
+set(LIST2 x y z)
+foreach(VAR1_1 VAR1_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+if (NOT DEFINED VAR1_1 OR NOT VAR1_1 STREQUAL ""
+ OR NOT DEFINED VAR1_2 OR NOT VAR1_2 STREQUAL "")
+ message(SEND_ERROR "Variables 'VAR1_1' or 'VAR1_2' not defined or wrong value.")
+endif()
+
+
+set (VAR2 OLD)
+foreach(VAR2 a b c)
+endforeach()
+if (NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR2' not defined or wrong value.")
+endif()
+
+set (VAR2_2 OLD)
+foreach(VAR2_1 VAR2_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+if (NOT DEFINED VAR2_1 OR NOT VAR2_1 STREQUAL ""
+ OR NOT DEFINED VAR2_2 OR NOT VAR2_2 STREQUAL "OLD")
+ message(SEND_ERROR "Variables 'VAR2_1' or 'VAR2_2' not defined or wrong value.")
+endif()
+
+
+set (VAR3 OLD CACHE STRING "")
+foreach(VAR3 a b c)
+endforeach()
+# a normal variable is defined, holding cache variable value
+unset(VAR3 CACHE)
+if (NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "OLD")
+ message(SEND_ERROR "Variable 'VAR3' not defined or wrong value.")
+endif()
+
+set (VAR3_2 OLD CACHE STRING "")
+foreach(VAR3_1 VAR3_2 IN ZIP_LISTS LIST1 LIST2)
+endforeach()
+# a normal variable is defined, holding cache variable value
+unset(VAR3_2 CACHE)
+if (NOT DEFINED VAR3_1 OR NOT VAR3_1 STREQUAL ""
+ OR NOT DEFINED VAR3_2 OR NOT VAR3_2 STREQUAL "OLD")
+ message(SEND_ERROR "Variables 'VAR3_1' or 'VAR3_2' not defined or wrong value.")
+endif()
diff --git a/Tests/RunCMake/get_property/directory_properties-stderr.txt b/Tests/RunCMake/get_property/directory_properties-stderr.txt
index 89f5618ee..be06f0ede 100644
--- a/Tests/RunCMake/get_property/directory_properties-stderr.txt
+++ b/Tests/RunCMake/get_property/directory_properties-stderr.txt
@@ -12,6 +12,10 @@ get_directory_property: -->CustomTop;InterfaceTop<--
get_property: -->CustomTop;InterfaceTop<--
get_directory_property: -->CustomSub;InterfaceSub<--
get_property: -->CustomSub;InterfaceSub<--
+get_directory_property: -->Imported1Top;Imported2Top<--
+get_property: -->Imported1Top;Imported2Top<--
+get_directory_property: -->Imported1Sub;Imported2Sub<--
+get_property: -->Imported1Sub;Imported2Sub<--
get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build<--
get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build<--
get_directory_property: -->[^<;]*/RunCMake/get_property<--
diff --git a/Tests/RunCMake/get_property/directory_properties.cmake b/Tests/RunCMake/get_property/directory_properties.cmake
index 9b978fd50..4dce52440 100644
--- a/Tests/RunCMake/get_property/directory_properties.cmake
+++ b/Tests/RunCMake/get_property/directory_properties.cmake
@@ -18,11 +18,16 @@ add_custom_target(CustomTop)
add_library(InterfaceTop INTERFACE)
add_library(my::InterfaceTop ALIAS InterfaceTop)
+add_library(Imported1Top INTERFACE IMPORTED)
+add_library(Imported2Top INTERFACE IMPORTED)
+
add_subdirectory(directory_properties)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" SUBDIRECTORIES)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" SUBDIRECTORIES)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" BUILDSYSTEM_TARGETS)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" BUILDSYSTEM_TARGETS)
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" IMPORTED_TARGETS)
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" IMPORTED_TARGETS)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" BINARY_DIR)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" SOURCE_DIR)
diff --git a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt
index 95106adca..9fab79967 100644
--- a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt
+++ b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt
@@ -5,5 +5,8 @@ add_custom_target(CustomSub)
add_library(InterfaceSub INTERFACE)
add_library(my::InterfaceSub ALIAS InterfaceSub)
+add_library(Imported1Sub INTERFACE IMPORTED)
+add_library(Imported2Sub INTERFACE IMPORTED)
+
add_test(Sub/test1 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test1")
add_test(Sub/test2 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test2")
diff --git a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake
index 7ed0773f9..cb0eb1879 100644
--- a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake
@@ -8,4 +8,5 @@ run_cmake(CustomConfig)
if(RunCMake_GENERATOR MATCHES "Visual Studio ([^9]|9[0-9])")
run_cmake(SkipGetTargetFrameworkProperties)
+ run_cmake(VSCSharpReference)
endif()
diff --git a/Tests/RunCMake/include_external_msproject/VSCSharpReference-check.cmake b/Tests/RunCMake/include_external_msproject/VSCSharpReference-check.cmake
new file mode 100644
index 000000000..71b8c1f9c
--- /dev/null
+++ b/Tests/RunCMake/include_external_msproject/VSCSharpReference-check.cmake
@@ -0,0 +1,36 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/internal.vcxproj" all_build)
+
+string(REGEX MATCH
+ "<ProjectReference.Include=.external.csproj.>.*</ProjectReference>"
+ ProjectReference
+ ${all_build}
+)
+
+if(ProjectReference STREQUAL "")
+ set(RunCMake_TEST_FAILED "${test} is being set unexpectedly.")
+else()
+ string(REGEX MATCH
+ "<ReferenceOutputAssembly>.*</ReferenceOutputAssembly>"
+ ReferenceOutputAssembly
+ ${ProjectReference}
+ )
+
+ if(NOT ReferenceOutputAssembly STREQUAL "")
+ string(REPLACE
+ "<ReferenceOutputAssembly>"
+ ""
+ ReferenceOutputAssemblyValue
+ ${ReferenceOutputAssembly}
+ )
+ string(REPLACE
+ "</ReferenceOutputAssembly>"
+ ""
+ ReferenceOutputAssemblyValue
+ ${ReferenceOutputAssemblyValue}
+ )
+
+ if(ReferenceOutputAssemblyValue MATCHES "[Fa][Ll][Ss][Ee]")
+ set(RunCMake_TEST_FAILED "Referenced C# project with ReferenceOutputAssembly set to false.")
+ endif()
+ endif()
+endif()
diff --git a/Tests/RunCMake/include_external_msproject/VSCSharpReference.cmake b/Tests/RunCMake/include_external_msproject/VSCSharpReference.cmake
new file mode 100644
index 000000000..6229e612a
--- /dev/null
+++ b/Tests/RunCMake/include_external_msproject/VSCSharpReference.cmake
@@ -0,0 +1,10 @@
+project(VSCSharpReference)
+
+include_external_msproject(external external.csproj)
+
+add_executable(internal
+ main.cpp
+)
+add_dependencies(internal
+ external
+)
diff --git a/Tests/RunCMake/install/FILES-directory-result.txt b/Tests/RunCMake/install/FILES-directory-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-directory-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/FILES-directory-stderr.txt b/Tests/RunCMake/install/FILES-directory-stderr.txt
new file mode 100644
index 000000000..469903732
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-directory-stderr.txt
@@ -0,0 +1 @@
+install FILES given directory
diff --git a/Tests/RunCMake/install/FILES-directory.cmake b/Tests/RunCMake/install/FILES-directory.cmake
new file mode 100644
index 000000000..1199cf77c
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-directory.cmake
@@ -0,0 +1,7 @@
+set(dst "${CMAKE_CURRENT_BINARY_DIR}/dst")
+set(src "${CMAKE_CURRENT_BINARY_DIR}/src")
+
+file(MAKE_DIRECTORY "${dst}")
+file(MAKE_DIRECTORY "${src}")
+
+install(FILES "${src}" DESTINATION "${dst}")
diff --git a/Tests/RunCMake/install/FILES-symlink-to-directory.cmake b/Tests/RunCMake/install/FILES-symlink-to-directory.cmake
new file mode 100644
index 000000000..ed7647008
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-symlink-to-directory.cmake
@@ -0,0 +1,9 @@
+set(dst "${CMAKE_CURRENT_BINARY_DIR}/dst")
+set(src "${CMAKE_CURRENT_BINARY_DIR}/src")
+set(lnk "${CMAKE_CURRENT_BINARY_DIR}/lnk")
+
+file(MAKE_DIRECTORY "${dst}")
+file(MAKE_DIRECTORY "${src}")
+file(CREATE_LINK "${src}" "${lnk}" SYMBOLIC)
+
+install(FILES "${lnk}" DESTINATION "${dst}")
diff --git a/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt
new file mode 100644
index 000000000..7ae660625
--- /dev/null
+++ b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported\.cmake:[0-9]+ \(install\):
+ install IMPORTED_RUNTIME_ARTIFACTS RUNTIME_DEPENDENCY_SET is not supported
+ on system "[^
+]*"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported.cmake b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported.cmake
new file mode 100644
index 000000000..04f199509
--- /dev/null
+++ b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported.cmake
@@ -0,0 +1,2 @@
+add_executable(exe IMPORTED)
+install(IMPORTED_RUNTIME_ARTIFACTS exe RUNTIME_DEPENDENCY_SET deps)
diff --git a/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-result.txt b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt
new file mode 100644
index 000000000..cab309b2c
--- /dev/null
+++ b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at RUNTIME_DEPENDENCY_SET-unsupported\.cmake:[0-9]+ \(install\):
+ install RUNTIME_DEPENDENCY_SET is not supported on system "[^
+]*"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported.cmake b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported.cmake
new file mode 100644
index 000000000..60772a0f3
--- /dev/null
+++ b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported.cmake
@@ -0,0 +1 @@
+install(RUNTIME_DEPENDENCY_SET deps)
diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake
index efd03df6f..f79a3ea74 100644
--- a/Tests/RunCMake/install/RunCMakeTest.cmake
+++ b/Tests/RunCMake/install/RunCMakeTest.cmake
@@ -44,7 +44,7 @@ function(check_installed expect)
do not match what we expected:
${expect}
in directory:
- ${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE)
+ ${CMAKE_INSTALL_PREFIX}\n" PARENT_SCOPE)
endif()
endfunction()
@@ -55,9 +55,9 @@ function(run_cmake_EDIT_RPATH_only case)
else()
# Sanity check against a platform known to be ELF-based
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
- message(FATAL_ERROR "Expected platform Linux to advertize itself as ELF-based, but it did not.")
+ message(FATAL_ERROR "Expected platform Linux to advertise itself as ELF-based, but it did not.")
elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX")
- message(FATAL_ERROR "Expected platform AIX to advertize itself as XCOFF-based, but it did not.")
+ message(FATAL_ERROR "Expected platform AIX to advertise itself as XCOFF-based, but it did not.")
else()
message(STATUS "${case} - SKIPPED (No ELF-based platform found)")
endif()
@@ -93,6 +93,10 @@ run_cmake(TARGETS-NAMELINK_COMPONENT-bad-all)
run_cmake(TARGETS-NAMELINK_COMPONENT-bad-exc)
run_cmake(FILES-DESTINATION-TYPE)
run_cmake(DIRECTORY-DESTINATION-TYPE)
+run_cmake(FILES-directory)
+if(NOT WIN32)
+ run_cmake(FILES-symlink-to-directory)
+endif()
set(RunCMake_TEST_OPTIONS "-DCMAKE_BUILD_TYPE:STRING=Debug")
run_install_test(FILES-RENAME)
@@ -170,8 +174,29 @@ run_install_test(FILES-PERMISSIONS)
run_install_test(TARGETS-RPATH)
run_install_test(InstallRequiredSystemLibraries)
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle)
+ run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$")
+ run_install_test(TARGETS-RUNTIME_DEPENDENCIES-nodep)
+ run_install_test(TARGETS-RUNTIME_DEPENDENCIES-empty)
+ set(RunCMake_TEST_OPTIONS "-DCMAKE_SYSTEM_NAME:STRING=${CMAKE_SYSTEM_NAME}")
+ run_cmake(TARGETS-RUNTIME_DEPENDENCIES-cross)
+ unset(RunCMake_TEST_OPTIONS)
+ run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict)
+ run_cmake(RuntimeDependencies-COMPONENTS)
+else()
+ run_cmake(TARGETS-RUNTIME_DEPENDENCIES-unsupported)
+ run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-unsupported)
+ run_cmake(IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported)
+ run_cmake(RUNTIME_DEPENDENCY_SET-unsupported)
+endif()
+
set(run_install_test_components 1)
run_install_test(FILES-EXCLUDE_FROM_ALL)
run_install_test(TARGETS-EXCLUDE_FROM_ALL)
run_install_test(TARGETS-NAMELINK_COMPONENT)
run_install_test(SCRIPT-COMPONENT)
+run_install_test(SCRIPT-ALL_COMPONENTS)
diff --git a/Tests/RunCMake/install/RuntimeDependencies-COMPONENTS.cmake b/Tests/RunCMake/install/RuntimeDependencies-COMPONENTS.cmake
new file mode 100644
index 000000000..4727de35f
--- /dev/null
+++ b/Tests/RunCMake/install/RuntimeDependencies-COMPONENTS.cmake
@@ -0,0 +1,39 @@
+enable_language(C)
+
+function(check_components value)
+ get_cmake_property(comp COMPONENTS)
+ if(NOT comp STREQUAL value)
+ message(FATAL_ERROR "Expected value of COMPONENTS:\n ${value}\nActual value of COMPONENTS:\n ${comp}")
+ endif()
+endfunction()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ add_library(tgt MODULE obj1.c)
+else()
+ add_executable(tgt main.c)
+endif()
+
+install(TARGETS tgt
+ RUNTIME_DEPENDENCIES
+ RUNTIME DESTINATION bin COMPONENT bin1
+ LIBRARY DESTINATION lib COMPONENT lib1
+ FRAMEWORK DESTINATION fw COMPONENT fw1
+ )
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ check_components("bin1;fw1;lib1")
+else()
+ check_components("bin1;lib1")
+endif()
+
+install(RUNTIME_DEPENDENCY_SET deps
+ RUNTIME DESTINATION bin COMPONENT bin2
+ LIBRARY DESTINATION lib COMPONENT lib2
+ FRAMEWORK DESTINATION fw COMPONENT fw2
+ )
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ check_components("bin1;fw1;fw2;lib1;lib2")
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ check_components("bin1;bin2;lib1")
+elseif()
+ check_components("bin1;lib1;lib2")
+endif()
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake
new file mode 100644
index 000000000..48d8e1aec
--- /dev/null
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake
@@ -0,0 +1 @@
+check_installed([[^empty1.txt;empty2.txt$]])
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake
new file mode 100644
index 000000000..48d8e1aec
--- /dev/null
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake
@@ -0,0 +1 @@
+check_installed([[^empty1.txt;empty2.txt$]])
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake
new file mode 100644
index 000000000..48d8e1aec
--- /dev/null
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake
@@ -0,0 +1 @@
+check_installed([[^empty1.txt;empty2.txt$]])
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake
new file mode 100644
index 000000000..aa3f9d1b7
--- /dev/null
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake
@@ -0,0 +1,5 @@
+install(
+ SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/install_script.cmake"
+ CODE "write_empty_file(empty2.txt)"
+ ALL_COMPONENTS
+ )
diff --git a/Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake b/Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake
index 4a55cd6f0..d0994694d 100644
--- a/Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake
+++ b/Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake
@@ -13,6 +13,21 @@ if(WIN32)
[[mylib/(lib)?lib1\.(dll\.a|lib)]]
[[mylib/(lib)?lib2\.(a|lib)]]
)
+elseif(MSYS)
+ set(_check_files
+ [[lib3]]
+ [[lib3/liblib3\.dll\.a]]
+ [[lib4]]
+ [[lib4/msys-lib4\.dll]]
+ [[mybin]]
+ [[mybin/exe\.exe]]
+ [[mybin/msys-lib1\.dll]]
+ [[myinclude]]
+ [[myinclude/obj3\.h]]
+ [[mylib]]
+ [[mylib/liblib1\.dll\.a]]
+ [[mylib/liblib2\.a]]
+ )
elseif(CYGWIN)
set(_check_files
[[lib3]]
diff --git a/Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake b/Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake
index 30f2266d1..6e13b84c2 100644
--- a/Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake
+++ b/Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake
@@ -15,6 +15,23 @@ if(WIN32)
[[lib4]]
[[lib4/(lib)?lib4\.dll]]
)
+elseif(MSYS)
+ set(_check_files
+ [[bin]]
+ [[bin/exe\.exe]]
+ [[bin/msys-lib1\.dll]]
+ [[include]]
+ [[include/obj1\.h]]
+ [[include/obj2\.h]]
+ [[include/obj3\.h]]
+ [[lib]]
+ [[lib/liblib1\.dll\.a]]
+ [[lib/liblib2\.a]]
+ [[lib3]]
+ [[lib3/liblib3\.dll\.a]]
+ [[lib4]]
+ [[lib4/msys-lib4\.dll]]
+ )
elseif(CYGWIN)
set(_check_files
[[bin]]
diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake
index bc9ebd192..e602af9b7 100644
--- a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake
+++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake
@@ -8,6 +8,16 @@ if(WIN32)
[[lib/(lib)?namelink-uns-dev\.dll]]
[[lib/(lib)?namelink-uns\.dll]]
)
+elseif(MSYS)
+ set(_check_files
+ [[lib]]
+ [[lib/msys-namelink-none\.dll]]
+ [[lib/msys-namelink-same-1\.dll]]
+ [[lib/msys-namelink-sep-1\.dll]]
+ [[lib/msys-namelink-skip-1\.dll]]
+ [[lib/msys-namelink-uns-1\.dll]]
+ [[lib/msys-namelink-uns-dev-1\.dll]]
+ )
elseif(CYGWIN)
set(_check_files
[[lib]]
diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake
index 3f6be686c..cd579eb56 100644
--- a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake
+++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake
@@ -6,6 +6,14 @@ if(WIN32)
[[lib/(lib)?namelink-sep\.dll]]
[[lib/(lib)?namelink-skip\.dll]]
)
+elseif(MSYS)
+ set(_check_files
+ [[lib]]
+ [[lib/msys-namelink-none\.dll]]
+ [[lib/msys-namelink-same-1\.dll]]
+ [[lib/msys-namelink-sep-1\.dll]]
+ [[lib/msys-namelink-skip-1\.dll]]
+ )
elseif(CYGWIN)
set(_check_files
[[lib]]
diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake
index 0033c88e4..ea68f4abc 100644
--- a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake
+++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake
@@ -4,6 +4,12 @@ if(WIN32)
[[lib/(lib)?namelink-uns-dev\.dll]]
[[lib/(lib)?namelink-uns\.dll]]
)
+elseif(MSYS)
+ set(_check_files
+ [[lib]]
+ [[lib/msys-namelink-uns-1\.dll]]
+ [[lib/msys-namelink-uns-dev-1\.dll]]
+ )
elseif(CYGWIN)
set(_check_files
[[lib]]
diff --git a/Tests/RunCMake/install/TARGETS-OUTPUT_NAME-all-check.cmake b/Tests/RunCMake/install/TARGETS-OUTPUT_NAME-all-check.cmake
index 5daecc815..91d5ef092 100644
--- a/Tests/RunCMake/install/TARGETS-OUTPUT_NAME-all-check.cmake
+++ b/Tests/RunCMake/install/TARGETS-OUTPUT_NAME-all-check.cmake
@@ -4,6 +4,8 @@ if(WIN32)
set(test45 [[bin/test4\.dll;bin/test4\.lib;bin/test5ar\.lib]])
check_installed("^bin;(${libtest45};${test123})|(${test123};${test45})\$")
+elseif(MSYS)
+ check_installed([[^bin;bin/libtest4\.dll\.a;bin/libtest5ar\.a;bin/msys-test4\.dll;bin/test1out\.exe;bin/test2deb\.exe;bin/test3exc\.exe$]])
elseif(CYGWIN)
check_installed([[^bin;bin/cygtest4\.dll;bin/libtest4\.dll\.a;bin/libtest5ar\.a;bin/test1out\.exe;bin/test2deb\.exe;bin/test3exc\.exe$]])
elseif(APPLE)
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-stderr.txt
new file mode 100644
index 000000000..b7bbb55ce
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-cross\.cmake:[0-9]+ \(install\):
+ install TARGETS RUNTIME_DEPENDENCIES is not supported when cross-compiling\.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross.cmake
new file mode 100644
index 000000000..36b2eb7b4
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross.cmake
@@ -0,0 +1,4 @@
+enable_language(C)
+
+add_executable(exe main.c)
+install(TARGETS exe RUNTIME_DEPENDENCIES)
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty-all-check.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty-all-check.cmake
new file mode 100644
index 000000000..dafc2a48b
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty-all-check.cmake
@@ -0,0 +1 @@
+check_installed([[^static;static/(liblib\.a|lib\.lib)$]])
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty.cmake
new file mode 100644
index 000000000..e46e1d9b2
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+
+add_library(lib STATIC obj1.c)
+
+install(TARGETS lib RUNTIME_DEPENDENCIES
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION static
+ FRAMEWORK DESTINATION fw
+ )
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-stderr.txt
new file mode 100644
index 000000000..6ab14f6c1
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework\.cmake:[0-9]+ \(install\):
+ install TARGETS RUNTIME_DEPENDENCIES given no FRAMEWORK DESTINATION
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework.cmake
new file mode 100644
index 000000000..36b2eb7b4
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework.cmake
@@ -0,0 +1,4 @@
+enable_language(C)
+
+add_executable(exe main.c)
+install(TARGETS exe RUNTIME_DEPENDENCIES)
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-stderr.txt
new file mode 100644
index 000000000..c7b49c73b
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle\.cmake:[0-9]+ \(install\):
+ install A runtime dependency set may only have one bundle executable\.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle.cmake
new file mode 100644
index 000000000..a848a24c3
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+add_executable(exe1 MACOSX_BUNDLE main.c)
+add_executable(exe2 MACOSX_BUNDLE main.c)
+
+install(TARGETS exe1 exe2
+ RUNTIME_DEPENDENCIES
+ BUNDLE DESTINATION bundles
+ FRAMEWORK DESTINATION fw
+ )
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep-all-check.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep-all-check.cmake
new file mode 100644
index 000000000..9f455b1ba
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep-all-check.cmake
@@ -0,0 +1 @@
+check_installed([[^bin;bin/exe(\.exe)?$]])
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep.cmake
new file mode 100644
index 000000000..02466561d
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+
+add_executable(exe main.c)
+
+install(TARGETS exe
+ RUNTIME_DEPENDENCIES
+ PRE_EXCLUDE_REGEXES ".*"
+ FRAMEWORK DESTINATION fw
+ )
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-stderr.txt
new file mode 100644
index 000000000..c098a4c4e
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-unsupported\.cmake:[0-9]+ \(install\):
+ install TARGETS RUNTIME_DEPENDENCIES is not supported on system "[^
+]*"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported.cmake
new file mode 100644
index 000000000..36b2eb7b4
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported.cmake
@@ -0,0 +1,4 @@
+enable_language(C)
+
+add_executable(exe main.c)
+install(TARGETS exe RUNTIME_DEPENDENCIES)
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-stderr.txt
new file mode 100644
index 000000000..e2484ec3b
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict\.cmake:[0-9]+ \(install\):
+ install TARGETS cannot have both RUNTIME_DEPENDENCIES and
+ RUNTIME_DEPENDENCY_SET\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict.cmake
new file mode 100644
index 000000000..f373b3b39
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict.cmake
@@ -0,0 +1,7 @@
+enable_language(C)
+
+add_executable(exe main.c)
+install(TARGETS exe
+ RUNTIME_DEPENDENCY_SET deps
+ RUNTIME_DEPENDENCIES
+ )
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt
new file mode 100644
index 000000000..f660346b4
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at TARGETS-RUNTIME_DEPENDENCY_SET-unsupported\.cmake:[0-9]+ \(install\):
+ install TARGETS RUNTIME_DEPENDENCY_SET is not supported on system "[^
+]*"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported.cmake
new file mode 100644
index 000000000..be0f507a4
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported.cmake
@@ -0,0 +1,4 @@
+enable_language(C)
+
+add_executable(exe main.c)
+install(TARGETS exe RUNTIME_DEPENDENCY_SET deps)
diff --git a/Tests/RunCMake/option/CMP0077-OLD-stderr.txt b/Tests/RunCMake/option/CMP0077-OLD-stderr.txt
new file mode 100644
index 000000000..9d963cba6
--- /dev/null
+++ b/Tests/RunCMake/option/CMP0077-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0077-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0077 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/project/ProjectIsTopLevel-stdout.txt b/Tests/RunCMake/project/ProjectIsTopLevel-stdout.txt
new file mode 100644
index 000000000..af8abfdfd
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectIsTopLevel-stdout.txt
@@ -0,0 +1,2 @@
+-- PROJECT_IS_TOP_LEVEL=ON
+-- ProjectIsTopLevel_IS_TOP_LEVEL=ON
diff --git a/Tests/RunCMake/project/ProjectIsTopLevel.cmake b/Tests/RunCMake/project/ProjectIsTopLevel.cmake
new file mode 100644
index 000000000..5a0af0aaa
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectIsTopLevel.cmake
@@ -0,0 +1,9 @@
+# no project() call, includer already calls project(${RunCMake_TEST} NONE)
+if(NOT DEFINED PROJECT_IS_TOP_LEVEL)
+ message(FATAL_ERROR "PROJECT_IS_TOP_LEVEL is not defined")
+endif()
+if(NOT DEFINED "CACHE{${RunCMake_TEST}_IS_TOP_LEVEL}")
+ message(FATAL_ERROR "IsTopLevel_IS_TOP_LEVEL is not defined")
+endif()
+message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
+message(STATUS "${RunCMake_TEST}_IS_TOP_LEVEL=${${RunCMake_TEST}_IS_TOP_LEVEL}")
diff --git a/Tests/RunCMake/project/ProjectIsTopLevelMultiple-stdout.txt b/Tests/RunCMake/project/ProjectIsTopLevelMultiple-stdout.txt
new file mode 100644
index 000000000..75d787f9e
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectIsTopLevelMultiple-stdout.txt
@@ -0,0 +1,3 @@
+-- PROJECT_IS_TOP_LEVEL=ON
+-- ProjectIsTopLevelMultiple_IS_TOP_LEVEL=ON
+-- IsTopLevel_IS_TOP_LEVEL=ON
diff --git a/Tests/RunCMake/project/ProjectIsTopLevelMultiple.cmake b/Tests/RunCMake/project/ProjectIsTopLevelMultiple.cmake
new file mode 100644
index 000000000..98ba55bc1
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectIsTopLevelMultiple.cmake
@@ -0,0 +1,14 @@
+# only one project() call, includer already calls project(${RunCMake_TEST} NONE)
+project(IsTopLevel NONE)
+if(NOT DEFINED PROJECT_IS_TOP_LEVEL)
+ message(FATAL_ERROR "PROJECT_IS_TOP_LEVEL is not defined")
+endif()
+if(NOT DEFINED "CACHE{${RunCMake_TEST}_IS_TOP_LEVEL}")
+ message(FATAL_ERROR "${RunCMake_TEST}_IS_TOP_LEVEL is not defined")
+endif()
+if(NOT DEFINED CACHE{IsTopLevel_IS_TOP_LEVEL})
+ message(FATAL_ERROR "IsTopLevel_IS_TOP_LEVEL is not defined")
+endif()
+message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
+message(STATUS "${RunCMake_TEST}_IS_TOP_LEVEL=${${RunCMake_TEST}_IS_TOP_LEVEL}")
+message(STATUS "IsTopLevel_IS_TOP_LEVEL=${IsTopLevel_IS_TOP_LEVEL}")
diff --git a/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory-stdout.txt b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory-stdout.txt
new file mode 100644
index 000000000..d9e15ff8d
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory-stdout.txt
@@ -0,0 +1,6 @@
+-- PROJECT_IS_TOP_LEVEL=ON
+-- PROJECT_IS_TOP_LEVEL=ON
+-- PROJECT_IS_TOP_LEVEL=OFF
+-- PROJECT_IS_TOP_LEVEL=ON
+-- ProjectIsTopLevelSubdirectory_IS_TOP_LEVEL=ON
+-- NotTopLevel_IS_TOP_LEVEL=OFF
diff --git a/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory.cmake b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory.cmake
new file mode 100644
index 000000000..b5df84b2f
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory.cmake
@@ -0,0 +1,8 @@
+# no project() call, includer already calls project(${RunCMake_TEST} NONE)
+message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
+
+add_subdirectory(ProjectIsTopLevelSubdirectory)
+
+message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
+message(STATUS "${RunCMake_TEST}_IS_TOP_LEVEL=${${RunCMake_TEST}_IS_TOP_LEVEL}")
+message(STATUS "NotTopLevel_IS_TOP_LEVEL=${NotTopLevel_IS_TOP_LEVEL}")
diff --git a/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory/CMakeLists.txt b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory/CMakeLists.txt
new file mode 100644
index 000000000..d2f16ea4c
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory/CMakeLists.txt
@@ -0,0 +1,5 @@
+message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
+
+project(NotTopLevel NONE)
+
+message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index 69146993b..349e8ac41 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -15,6 +15,9 @@ run_cmake(ProjectDescriptionNoArg2)
run_cmake(ProjectHomepage)
run_cmake(ProjectHomepage2)
run_cmake(ProjectHomepageNoArg)
+run_cmake(ProjectIsTopLevel)
+run_cmake(ProjectIsTopLevelMultiple)
+run_cmake(ProjectIsTopLevelSubdirectory)
run_cmake(ProjectTwice)
run_cmake(VersionAndLanguagesEmpty)
run_cmake(VersionEmpty)
diff --git a/Tests/RunCMake/target_compile_options/Order-build-stdout.txt b/Tests/RunCMake/target_compile_options/Order-build-stdout.txt
new file mode 100644
index 000000000..c210ff213
--- /dev/null
+++ b/Tests/RunCMake/target_compile_options/Order-build-stdout.txt
@@ -0,0 +1,3 @@
+-w +-O +-O0 [^
+]*-O1 +-O2 +-O3 [^
+]*CMakeFiles[\/]order\.dir[\/](Custom[\/])?order\.c\.o
diff --git a/Tests/RunCMake/target_compile_options/Order.cmake b/Tests/RunCMake/target_compile_options/Order.cmake
new file mode 100644
index 000000000..3d59b16c9
--- /dev/null
+++ b/Tests/RunCMake/target_compile_options/Order.cmake
@@ -0,0 +1,19 @@
+get_property (isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(isMultiConfig)
+ set(CMAKE_CONFIGURATION_TYPES "Custom" CACHE STRING "" FORCE)
+else()
+ set(CMAKE_BUILD_TYPE "Custom" CACHE STRING "" FORCE)
+endif()
+enable_language(C)
+
+string(APPEND CMAKE_C_FLAGS " -w -O")
+set(CMAKE_C_FLAGS_CUSTOM "-O0")
+
+add_executable(order order.c)
+set_property(TARGET order APPEND PROPERTY COMPILE_OPTIONS -O1)
+
+add_library(iface INTERFACE)
+set_property(TARGET iface APPEND PROPERTY INTERFACE_COMPILE_OPTIONS -O2)
+target_link_libraries(order PRIVATE iface)
+
+set_property(SOURCE order.c PROPERTY COMPILE_OPTIONS -O3)
diff --git a/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake
index 9f51a9a52..806ae79b0 100644
--- a/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake
@@ -19,3 +19,16 @@ if (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
run_cmake_target(CMP0101-BEFORE_keyword OLD CMP0101_OLD)
run_cmake_target(CMP0101-BEFORE_keyword NEW CMP0101_NEW)
endif()
+
+function(run_Order)
+ run_cmake_with_options(Order)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Order-build)
+ set(RunCMake_TEST_OUTPUT_MERGE 1)
+ run_cmake_command(Order-build ${CMAKE_COMMAND} --build . --verbose --config Custom)
+endfunction()
+if(RunCMake_GENERATOR MATCHES "Ninja|Make" AND
+ CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$" AND
+ NOT CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
+ run_Order()
+endif()
diff --git a/Tests/RunCMake/target_compile_options/order.c b/Tests/RunCMake/target_compile_options/order.c
new file mode 100644
index 000000000..1bd81eafb
--- /dev/null
+++ b/Tests/RunCMake/target_compile_options/order.c
@@ -0,0 +1,7 @@
+#ifndef __OPTIMIZE__
+# error "Optimizations not enabled!"
+#endif
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stderr.txt
new file mode 100644
index 000000000..c6645054f
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0079-iface-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0079 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/CMP0079-link-OLD-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0079-link-OLD-stderr.txt
index 0b4c4c683..14f478996 100644
--- a/Tests/RunCMake/target_link_libraries/CMP0079-link-OLD-stderr.txt
+++ b/Tests/RunCMake/target_link_libraries/CMP0079-link-OLD-stderr.txt
@@ -1,4 +1,15 @@
-^CMake Error at CMP0079-link/CMakeLists.txt:[0-9]+ \(target_link_libraries\):
+^CMake Deprecation Warning at CMP0079-link-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0079 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\)
++
+CMake Error at CMP0079-link/CMakeLists.txt:[0-9]+ \(target_link_libraries\):
Attempt to add link library "foo" to target "top" which is not built in
this directory.
diff --git a/Tests/SetLang/CMakeLists.txt b/Tests/SetLang/CMakeLists.txt
index 3eb918542..80348ab92 100644
--- a/Tests/SetLang/CMakeLists.txt
+++ b/Tests/SetLang/CMakeLists.txt
@@ -9,6 +9,10 @@ set_source_files_properties(foo.c bar.c PROPERTIES LANGUAGE CXX)
target_link_libraries(SetLang foo)
set_target_properties(SetLang PROPERTIES LINKER_LANGUAGE CXX)
+# Windows defender blocks SetLang executable (https://cygwin.com/pipermail/cygwin/2021-January/247508.html)
+# Coordinate this name with 'Tests/CMakeLists.txt'.
+set_target_properties(SetLang PROPERTIES OUTPUT_NAME "SetLangX")
+
# VS generators historically tolerated target-wide -TP flags added
# by project code, so cover that case to preserve the behavior.
if(CMAKE_GENERATOR MATCHES "^Visual Studio" AND "x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC")
diff --git a/Tests/StringFileTest/CMakeLists.txt b/Tests/StringFileTest/CMakeLists.txt
index faf3bc90b..068fae994 100644
--- a/Tests/StringFileTest/CMakeLists.txt
+++ b/Tests/StringFileTest/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(StringFileTest)
include_directories(${StringFileTest_BINARY_DIR})
diff --git a/Tests/SubDirSpaces/CMakeLists.txt b/Tests/SubDirSpaces/CMakeLists.txt
index 0d45db85c..ecd4353b7 100644
--- a/Tests/SubDirSpaces/CMakeLists.txt
+++ b/Tests/SubDirSpaces/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(SUBDIR)
# Some systems do not seem to support rpath with spaces.
diff --git a/Tests/TargetName/CMakeLists.txt b/Tests/TargetName/CMakeLists.txt
index 9729d21ff..21752b7fd 100644
--- a/Tests/TargetName/CMakeLists.txt
+++ b/Tests/TargetName/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(TargetName)
add_subdirectory(executables)
diff --git a/Tests/TestDriver/CMakeLists.txt b/Tests/TestDriver/CMakeLists.txt
index 663ecab55..3cc69c03e 100644
--- a/Tests/TestDriver/CMakeLists.txt
+++ b/Tests/TestDriver/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(TestDriverTest)
set(Extra_SRCS testExtraStuff.cxx testExtraStuff2.cxx )
diff --git a/Tests/TestsWorkingDirectory/CMakeLists.txt b/Tests/TestsWorkingDirectory/CMakeLists.txt
index 6a6e9b6c7..2a0b01565 100644
--- a/Tests/TestsWorkingDirectory/CMakeLists.txt
+++ b/Tests/TestsWorkingDirectory/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.8.12)
project(TestsWorkingDirectoryProj)
add_executable(WorkingDirectory main.c)
diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt
index 0d44f2184..d0c413fb1 100644
--- a/Tests/TryCompile/CMakeLists.txt
+++ b/Tests/TryCompile/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(TryCompile)
macro(TEST_ASSERT value msg)
diff --git a/Tests/TryCompile/Inner/CMakeLists.txt b/Tests/TryCompile/Inner/CMakeLists.txt
index d62bcc4dd..d8c22d00a 100644
--- a/Tests/TryCompile/Inner/CMakeLists.txt
+++ b/Tests/TryCompile/Inner/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.8.12)
project(TryCompileInner C)
try_compile(SHOULD_PASS
diff --git a/Tests/UseSWIG/CMakeLists.txt b/Tests/UseSWIG/CMakeLists.txt
index d08c59ca3..f1b2f3214 100644
--- a/Tests/UseSWIG/CMakeLists.txt
+++ b/Tests/UseSWIG/CMakeLists.txt
@@ -66,7 +66,8 @@ add_test(NAME UseSWIG.BasicPerl COMMAND
--build-options ${build_options}
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
-if(SWIG_FOUND AND NOT SWIG_VERSION VERSION_LESS "4.0.2")
+if(SWIG_FOUND AND NOT SWIG_VERSION VERSION_LESS "4.0.2"
+ AND CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode")
add_test(NAME UseSWIG.Depfile.BasicPython COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test
diff --git a/Tests/VSExternalInclude/CMakeLists.txt b/Tests/VSExternalInclude/CMakeLists.txt
index 8ca725249..a3fd8d8eb 100644
--- a/Tests/VSExternalInclude/CMakeLists.txt
+++ b/Tests/VSExternalInclude/CMakeLists.txt
@@ -1,7 +1,7 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
project(VSExternalInclude)
-if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[012456]")
+if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[0124567]")
set(PROJECT_EXT vcxproj)
else()
set(PROJECT_EXT vcproj)
@@ -55,7 +55,7 @@ add_dependencies(VSExternalInclude lib2)
# and the sln file can no longer be the only source
# of that depend. So, for VS 10 make the executable
# depend on lib1 and lib2
-if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[012456]")
+if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[0124567]")
add_dependencies(VSExternalInclude lib1)
endif()
diff --git a/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt b/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt
index abd062836..950ec25d5 100644
--- a/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt
+++ b/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt
@@ -43,4 +43,9 @@ if(CMAKE_Fortran_COMPILER_ID MATCHES SunPro)
target_link_libraries(hello PRIVATE sunquad)
endif()
endif()
+elseif(CMAKE_Fortran_COMPILER_ID MATCHES Fujitsu)
+ # Fujitsu Fortran doesn't automatically link its runtime libraries into
+ # SOs
+ target_link_libraries(world PRIVATE fj90i fj90f fjsrcinfo)
+ target_link_libraries(hello PRIVATE fj90i fj90f fjsrcinfo)
endif()
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index a880f7a81..0ccb72124 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.1...3.18 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.1...3.19 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 c2aced594..f1bdcc4ca 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -21,6 +21,7 @@
{ include: [ "<wctype.h>", public, "<cwctype>", public ] },
# HACK: check whether this can be removed with next iwyu release.
+ { include: [ "<bits/cxxabi_forced.h>", private, "<ctime>", public ] },
{ include: [ "<bits/shared_ptr.h>", private, "<memory>", public ] },
{ include: [ "<bits/std_function.h>", private, "<functional>", public ] },
{ include: [ "<bits/refwrap.h>", private, "<functional>", public ] },
@@ -96,6 +97,7 @@
{ symbol: [ "std::enable_if<true, std::chrono::duration<long, std::ratio<1, 1> > >::type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::enable_if<true, std::chrono::duration<long, std::ratio<60, 1> > >::type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::enable_if<true, std::chrono::duration<long, std::ratio<1, 1000> > >::type", private, "\"cmConfigure.h\"", public ] },
+ { symbol: [ "__gnu_cxx::__enable_if<true, bool>::__type", private, "\"cmConfigure.h\"", public ] },
# Wrappers for 3rd-party libraries
{ include: [ "@<.*curl/curlver.h>", private, "<cm3p/curl/curl.h>", public ] },
diff --git a/Utilities/Scripts/BoostScanDeps.cmake b/Utilities/Scripts/BoostScanDeps.cmake
index 5794d03e8..14c7f3cf8 100644
--- a/Utilities/Scripts/BoostScanDeps.cmake
+++ b/Utilities/Scripts/BoostScanDeps.cmake
@@ -20,7 +20,7 @@
# "component". For each component, all the headers will be scanned to
# determine the components it depends upon by following all the
# possible includes from this component. This is to match the
-# behaviour of autolinking.
+# behavior of autolinking.
# Written by Roger Leigh <rleigh@codelibre.net>
@@ -86,7 +86,7 @@ function(_Boost_FIND_COMPONENT_DEPENDENCIES component includedir _ret_libs)
set(library_component TRUE)
set(_boost_unprocessed_headers "${BOOST_DIR}/test/test_exec_monitor.hpp")
else()
- # Default behaviour where header directory is the same as the library name.
+ # Default behavior where header directory is the same as the library name.
file(GLOB_RECURSE _boost_unprocessed_headers
RELATIVE "${includedir}"
"${includedir}/boost/${component}/*")
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 16cdd6575..34ff4de57 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@cool.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_75_0"
+readonly tag="curl-7_77_0"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Scripts/update-expat.bash b/Utilities/Scripts/update-expat.bash
index 75e492a1c..a052c0edd 100755
--- a/Utilities/Scripts/update-expat.bash
+++ b/Utilities/Scripts/update-expat.bash
@@ -8,7 +8,7 @@ readonly name="expat"
readonly ownership="Expat Upstream <kwrobot@kitware.com>"
readonly subtree="Utilities/cmexpat"
readonly repo="https://github.com/libexpat/libexpat.git"
-readonly tag="R_2_2_10"
+readonly tag="R_2_4_1"
readonly shortlog=false
readonly paths="
expat/lib/asciitab.h
diff --git a/Utilities/Scripts/update-liblzma.bash b/Utilities/Scripts/update-liblzma.bash
index fdf66b3ec..a5a71750e 100755
--- a/Utilities/Scripts/update-liblzma.bash
+++ b/Utilities/Scripts/update-liblzma.bash
@@ -8,12 +8,17 @@ readonly name="liblzma"
readonly ownership="liblzma upstream <xz-devel@tukaani.org>"
readonly subtree="Utilities/cmliblzma"
readonly repo="https://git.tukaani.org/xz.git"
-readonly tag="v5.2.4"
+readonly tag="v5.2.5"
readonly shortlog=false
readonly paths="
COPYING
src/common/common_w32res.rc
+ src/common/mythread.h
src/common/sysdefs.h
+ src/common/tuklib_common.h
+ src/common/tuklib_config.h
+ src/common/tuklib_cpucores.c
+ src/common/tuklib_cpucores.h
src/common/tuklib_integer.h
src/liblzma/
"
diff --git a/Utilities/Scripts/update-third-party.bash b/Utilities/Scripts/update-third-party.bash
index fcab871bd..0d0a667c1 100644
--- a/Utilities/Scripts/update-third-party.bash
+++ b/Utilities/Scripts/update-third-party.bash
@@ -89,7 +89,7 @@ readonly basehash_regex="$name $regex_date ([0-9a-f]*)"
# Check for an empty destination directory on disk. By checking on disk and
# not in the repo it allows a library to be freshly re-inialized in a single
# commit rather than first deleting the old copy in one commit and adding the
-# new copy in a seperate commit.
+# new copy in a separate commit.
if [ ! -d "$(git rev-parse --show-toplevel)/$subtree" ]; then
readonly basehash=""
else
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index f989907b4..32efd4842 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.1...3.18 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.1...3.19 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)
@@ -22,6 +22,7 @@ option(SPHINX_MAN "Build man pages with Sphinx" OFF)
option(SPHINX_HTML "Build html help with Sphinx" OFF)
option(SPHINX_SINGLEHTML "Build html single page help with Sphinx" OFF)
option(SPHINX_QTHELP "Build Qt help with Sphinx" OFF)
+option(SPHINX_LATEXPDF "Build PDF help with Sphinx using LaTeX" OFF)
option(SPHINX_TEXT "Build text help with Sphinx (not installed)" OFF)
find_program(SPHINX_EXECUTABLE
NAMES sphinx-build
@@ -33,7 +34,7 @@ separate_arguments(sphinx_flags UNIX_COMMAND "${SPHINX_FLAGS}")
mark_as_advanced(SPHINX_TEXT)
mark_as_advanced(SPHINX_FLAGS)
-if(NOT SPHINX_INFO AND NOT SPHINX_MAN AND NOT SPHINX_HTML AND NOT SPHINX_SINGLEHTML AND NOT SPHINX_QTHELP AND NOT SPHINX_TEXT)
+if(NOT SPHINX_INFO AND NOT SPHINX_MAN AND NOT SPHINX_HTML AND NOT SPHINX_SINGLEHTML AND NOT SPHINX_QTHELP AND NOT SPHINX_TEXT AND NOT SPHINX_LATEXPDF)
return()
elseif(NOT SPHINX_EXECUTABLE)
message(FATAL_ERROR "SPHINX_EXECUTABLE (sphinx-build) is not found!")
@@ -117,28 +118,51 @@ if(SPHINX_QTHELP)
${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake.qhcp
)
endif()
-
+if(SPHINX_LATEXPDF)
+ list(APPEND doc_formats latexpdf)
+endif()
set(doc_format_outputs "")
set(doc_format_last "")
foreach(format ${doc_formats})
set(doc_format_output "doc_format_${format}")
set(doc_format_log "build-${format}.log")
- add_custom_command(
- OUTPUT ${doc_format_output}
- COMMAND ${SPHINX_EXECUTABLE}
- -c ${CMAKE_CURRENT_BINARY_DIR}
- -d ${CMAKE_CURRENT_BINARY_DIR}/doctrees
- -b ${format}
- ${sphinx_flags}
- ${CMake_SOURCE_DIR}/Help
- ${CMAKE_CURRENT_BINARY_DIR}/${format}
- > ${doc_format_log} # log stdout, pass stderr
- ${${format}_extra_commands}
- DEPENDS ${doc_format_last}
- COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}"
- VERBATIM
- )
+ if(format STREQUAL "latexpdf")
+ # This format does not use builder (-b) but make_mode (-M) which expects
+ # arguments in peculiar order
+ add_custom_command(
+ OUTPUT ${doc_format_output}
+ COMMAND ${SPHINX_EXECUTABLE}
+ -M ${format}
+ ${CMake_SOURCE_DIR}/Help
+ ${CMAKE_CURRENT_BINARY_DIR}/${format}
+ -c ${CMAKE_CURRENT_BINARY_DIR}
+ -d ${CMAKE_CURRENT_BINARY_DIR}/doctrees
+ ${sphinx_flags}
+ > ${doc_format_log} # log stdout, pass stderr
+ ${${format}_extra_commands}
+ DEPENDS ${doc_format_last}
+ COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}"
+ VERBATIM
+ )
+ else()
+ # other formats use standard builder (-b) mode
+ add_custom_command(
+ OUTPUT ${doc_format_output}
+ COMMAND ${SPHINX_EXECUTABLE}
+ -c ${CMAKE_CURRENT_BINARY_DIR}
+ -d ${CMAKE_CURRENT_BINARY_DIR}/doctrees
+ -b ${format}
+ ${sphinx_flags}
+ ${CMake_SOURCE_DIR}/Help
+ ${CMAKE_CURRENT_BINARY_DIR}/${format}
+ > ${doc_format_log} # log stdout, pass stderr
+ ${${format}_extra_commands}
+ DEPENDS ${doc_format_last}
+ COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}"
+ VERBATIM
+ )
+ endif()
set_property(SOURCE ${doc_format_output} PROPERTY SYMBOLIC 1)
list(APPEND doc_format_outputs ${doc_format_output})
set(doc_format_last ${doc_format_output})
@@ -219,3 +243,10 @@ if(SPHINX_QTHELP)
DESTINATION ${CMAKE_DOC_DIR} ${COMPONENT}
)
endif()
+
+if(SPHINX_LATEXPDF)
+ CMake_OPTIONAL_COMPONENT(sphinx-latexpdf)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/latexpdf/latex/CMake.pdf
+ DESTINATION ${CMAKE_DOC_DIR} ${COMPONENT}
+ )
+endif()
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index ece4bf56b..9215e1498 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -20,7 +20,7 @@ from pygments.lexer import bygroups
# - [\.\+-] are needed for string constants like gtk+-2.0
# - Unix paths are recognized by '/'; support for Windows paths may be added if needed
# - (\\.) allows for \-escapes (used in manual/cmake-language.7)
-# - $<..$<..$>..> nested occurence in cmake-buildsystem
+# - $<..$<..$>..> nested occurrence in cmake-buildsystem
# - Nested variable evaluations are only supported in a limited capacity. Only
# one level of nesting is supported and at most one nested variable can be present.
@@ -260,6 +260,8 @@ class CMakeTransform(Transform):
# Insert the object link target.
if objtype == 'command':
targetname = title.lower()
+ elif objtype == 'guide' and not tail.endswith('/index'):
+ targetname = tail
else:
if objtype == 'genex':
m = CMakeXRefRole._re_genex.match(title)
@@ -312,6 +314,7 @@ class CMakeXRefRole(XRefRole):
_re = re.compile(r'^(.+?)(\s*)(?<!\x00)<(.*?)>$', re.DOTALL)
_re_sub = re.compile(r'^([^()\s]+)\s*\(([^()]*)\)$', re.DOTALL)
_re_genex = re.compile(r'^\$<([^<>:]+)(:[^<>]+)?>$', re.DOTALL)
+ _re_guide = re.compile(r'^([^<>/]+)/([^<>]*)$', re.DOTALL)
def __call__(self, typ, rawtext, text, *args, **keys):
# Translate CMake command cross-references of the form:
@@ -326,6 +329,10 @@ class CMakeXRefRole(XRefRole):
m = CMakeXRefRole._re_genex.match(text)
if m:
text = '%s <%s>' % (text, m.group(1))
+ elif typ == 'cmake:guide':
+ m = CMakeXRefRole._re_guide.match(text)
+ if m:
+ text = '%s <%s>' % (m.group(2), text)
# CMake cross-reference targets frequently contain '<' so escape
# any explicit `<target>` with '<' not preceded by whitespace.
while True:
@@ -369,6 +376,10 @@ class CMakeXRefTransform(Transform):
continue
objname = ref['reftarget']
+ if objtype == 'guide' and CMakeXRefRole._re_guide.match(objname):
+ # Do not index cross-references to guide sections.
+ continue
+
targetnum = env.new_serialno('index-%s:%s' % (objtype, objname))
targetid = 'index-%s-%s:%s' % (targetnum, objtype, objname)
diff --git a/Utilities/cmThirdPartyChecks.cmake b/Utilities/cmThirdPartyChecks.cmake
index 4ccfdfc72..bab30463f 100644
--- a/Utilities/cmThirdPartyChecks.cmake
+++ b/Utilities/cmThirdPartyChecks.cmake
@@ -83,6 +83,7 @@ if(WIN32)
set(HAVE_GETPAGESIZE 0)
set(HAVE_GETPEERNAME 1)
set(HAVE_GETPID 1)
+ set(HAVE_GETPPID 0)
set(HAVE_GETPROTOBYNAME 1)
set(HAVE_GETPWNAM_R 0)
set(HAVE_GETPWUID_R 0)
@@ -165,6 +166,8 @@ if(WIN32)
set(HAVE_SIG_ATOMIC_T_NOT_VOLATILE 1)
set(HAVE_SIGINTERRUPT 0)
set(HAVE_SIGNAL_H 1)
+ set(HAVE_SIZEOF_ADDRESS_FAMILY 0)
+ set(HAVE_SIZEOF_SA_FAMILY_T 0)
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 0)
set(HAVE_SPAWN_H 0)
set(HAVE_SSL_H 0)
@@ -249,6 +252,7 @@ if(WIN32)
set(HAVE_WINSOCK2_H 1)
set(HAVE_WINSOCK_H 1)
set(HAVE_WS2TCPIP_H 1)
+ set(USE_WINCRYPT 1) # We do not need to build as a Windows App.
# UNIX integer id types do not exist on Windows.
set(HAVE_ID_T 0)
@@ -284,13 +288,16 @@ if(WIN32)
set(ARCHIVE_CRYPTO_SHA256_LIBC3 0)
set(ARCHIVE_CRYPTO_SHA256_LIBMD 0)
set(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM 0)
+ set(ARCHIVE_CRYPTO_SHA256_WIN 0)
set(ARCHIVE_CRYPTO_SHA384_LIBC 0)
set(ARCHIVE_CRYPTO_SHA384_LIBC2 0)
set(ARCHIVE_CRYPTO_SHA384_LIBC3 0)
set(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM 0)
+ set(ARCHIVE_CRYPTO_SHA384_WIN 0)
set(ARCHIVE_CRYPTO_SHA512_LIBC 0)
set(ARCHIVE_CRYPTO_SHA512_LIBC2 0)
set(ARCHIVE_CRYPTO_SHA512_LIBC3 0)
set(ARCHIVE_CRYPTO_SHA512_LIBMD 0)
set(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM 0)
+ set(ARCHIVE_CRYPTO_SHA512_WIN 0)
endif()
diff --git a/Utilities/cmbzip2/CMakeLists.txt b/Utilities/cmbzip2/CMakeLists.txt
index 9b53b0f12..ff90bb684 100644
--- a/Utilities/cmbzip2/CMakeLists.txt
+++ b/Utilities/cmbzip2/CMakeLists.txt
@@ -2,7 +2,7 @@ project(bzip2)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmcurl/CMake/CurlTests.c b/Utilities/cmcurl/CMake/CurlTests.c
index 949910d5e..2fcce1bb3 100644
--- a/Utilities/cmcurl/CMake/CurlTests.c
+++ b/Utilities/cmcurl/CMake/CurlTests.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -214,24 +214,6 @@ if (sizeof (bool *) )
#include <float.h>
int main() { return 0; }
#endif
-#ifdef RETSIGTYPE_TEST
-#include <sys/types.h>
-#include <signal.h>
-#ifdef signal
-# undef signal
-#endif
-#ifdef __cplusplus
-extern "C" void (*signal (int, void (*)(int)))(int);
-#else
-void (*signal ()) ();
-#endif
-
-int
-main ()
-{
- return 0;
-}
-#endif
#ifdef HAVE_INET_NTOA_R_DECL
#include <arpa/inet.h>
diff --git a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
index 9307381ef..c39355711 100644
--- a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
+++ b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2021, 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
@@ -86,8 +86,6 @@ if(NOT UNIX)
set(HAVE_INET_ADDR 1)
set(HAVE_INET_NTOA 1)
set(HAVE_INET_NTOA_R 0)
- set(HAVE_TCGETATTR 0)
- set(HAVE_TCSETATTR 0)
set(HAVE_PERROR 1)
set(HAVE_CLOSESOCKET 1)
set(HAVE_SETVBUF 0)
@@ -131,7 +129,6 @@ if(NOT UNIX)
set(HAVE_GETADDRINFO 0)
endif()
set(STDC_HEADERS 1)
- set(RETSIGTYPE_TEST 1)
set(HAVE_SIGACTION 0)
set(HAVE_MACRO_SIGSETJMP 0)
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 4fb93615c..16ef037cc 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -15,6 +15,7 @@ set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?")
set(CURL_DISABLE_FILE OFF CACHE INTERNAL "Disable curl file protocol?")
set(CURL_DISABLE_FTP OFF CACHE INTERNAL "Disable curl ftp protocol?")
set(CURL_DISABLE_GOPHER ON CACHE INTERNAL "Disable curl gopher protocol?")
+set(CURL_DISABLE_HSTS ON)
set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?")
set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?")
set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?")
@@ -28,6 +29,7 @@ set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?")
set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?")
set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?")
set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity")
+set(CURL_ENABLE_EXPORT_TARGET OFF)
set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols")
set(CURL_LTO OFF CACHE INTERNAL "Turn on compiler Link Time Optimizations")
set(CURL_STATIC_CRT OFF CACHE INTERNAL "Set to ON to build libcurl with static CRT on Windows (/MT).")
@@ -50,6 +52,7 @@ set(USE_LIBIDN2 ON)
set(USE_NGHTTP2 ON)
set(USE_NGTCP2 OFF)
set(USE_QUICHE OFF)
+set(USE_WIN32_IDN OFF)
set(USE_WIN32_LDAP OFF CACHE INTERNAL "No curl Windows LDAP")
if(CMAKE_USE_OPENSSL)
elseif(WIN32)
@@ -97,7 +100,7 @@ endif(APPLE)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
@@ -304,6 +307,9 @@ mark_as_advanced(CURL_DISABLE_GOPHER)
option(CURL_DISABLE_MQTT "to disable MQTT" OFF)
mark_as_advanced(CURL_DISABLE_MQTT)
+option(CURL_ENABLE_EXPORT_TARGET "to enable cmake export target" ON)
+mark_as_advanced(CURL_ENABLE_EXPORT_TARGET)
+
if(HTTP_ONLY)
set(CURL_DISABLE_DICT ON)
set(CURL_DISABLE_FILE ON)
@@ -323,6 +329,8 @@ endif()
option(CURL_DISABLE_ALTSVC "to disable alt-svc support" OFF)
mark_as_advanced(CURL_DISABLE_ALTSVC)
+option(CURL_DISABLE_HSTS "to disable HSTS support" OFF)
+mark_as_advanced(CURL_DISABLE_HSTS)
option(CURL_DISABLE_COOKIES "to disable cookies support" OFF)
mark_as_advanced(CURL_DISABLE_COOKIES)
option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF)
@@ -433,7 +441,6 @@ check_function_exists(gethostname HAVE_GETHOSTNAME)
if(WIN32)
check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32)
check_library_exists_concat("winmm" getch HAVE_LIBWINMM)
- list(APPEND CURL_LIBS "advapi32")
endif()
# check SSL libraries
@@ -478,7 +485,6 @@ if(CMAKE_USE_SCHANNEL)
set(SSL_ENABLED ON)
set(USE_SCHANNEL ON) # Windows native SSL/TLS support
set(USE_WINDOWS_SSPI ON) # CMAKE_USE_SCHANNEL implies CURL_WINDOWS_SSPI
- list(APPEND CURL_LIBS "crypt32")
endif()
if(CURL_WINDOWS_SSPI)
set(USE_WINDOWS_SSPI ON)
@@ -505,6 +511,14 @@ if(CMAKE_USE_SECTRANSP)
list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
endif()
+if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ find_library(SYSTEMCONFIGURATION_FRAMEWORK "SystemConfiguration")
+ if(NOT SYSTEMCONFIGURATION_FRAMEWORK)
+ message(FATAL_ERROR "SystemConfiguration framework not found")
+ endif()
+ list(APPEND CURL_LIBS "${SYSTEMCONFIGURATION_FRAMEWORK}")
+endif()
+
if(CMAKE_USE_OPENSSL)
find_package(OpenSSL)
if(NOT OpenSSL_FOUND)
@@ -633,10 +647,6 @@ if(USE_QUICHE)
cmake_pop_check_state()
endif()
-if(WIN32)
- set(USE_WIN32_CRYPTO ON)
-endif()
-
if(NOT CURL_DISABLE_LDAP)
if(WIN32)
option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
@@ -753,6 +763,14 @@ if(USE_LIBIDN2)
check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
endif()
+if(WIN32)
+ option(USE_WIN32_IDN "Use WinIDN for IDN support" OFF)
+ if(USE_WIN32_IDN)
+ 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)
@@ -988,7 +1006,8 @@ elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
- set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
+ set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}" CACHE STRING
+ "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
break()
endif()
@@ -997,7 +1016,8 @@ elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET))
if(EXISTS "/etc/ssl/certs")
- set(CURL_CA_PATH "/etc/ssl/certs")
+ set(CURL_CA_PATH "/etc/ssl/certs" CACHE STRING
+ "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
endif()
endif()
@@ -1016,9 +1036,7 @@ if(NOT UNIX)
check_include_file_concat("winsock.h" HAVE_WINSOCK_H)
check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H)
check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H)
- if(NOT CURL_WINDOWS_SSPI AND USE_OPENSSL)
- set(CURL_LIBS ${CURL_LIBS} "crypt32")
- endif()
+ check_include_file_concat("wincrypt.h" HAVE_WINCRYPT_H)
else()
set(HAVE_WINDOWS_H 0)
set(HAVE_WINSOCK_H 0)
@@ -1128,20 +1146,18 @@ 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(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR)
check_symbol_exists(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA)
check_symbol_exists(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R)
-check_symbol_exists(tcsetattr "${CURL_INCLUDES}" HAVE_TCSETATTR)
-check_symbol_exists(tcgetattr "${CURL_INCLUDES}" HAVE_TCGETATTR)
-check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR)
check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
-check_symbol_exists(setvbuf "${CURL_INCLUDES}" HAVE_SETVBUF)
check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP)
check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
-check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT)
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)
@@ -1191,6 +1207,16 @@ if(HAVE_FSETXATTR)
endforeach()
endif()
+set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
+check_type_size("sa_family_t" SIZEOF_SA_FAMILY_T)
+set(HAVE_SA_FAMILY_T ${HAVE_SIZEOF_SA_FAMILY_T})
+set(CMAKE_EXTRA_INCLUDE_FILES "")
+
+set(CMAKE_EXTRA_INCLUDE_FILES "ws2def.h")
+check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY)
+set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY})
+set(CMAKE_EXTRA_INCLUDE_FILES "")
+
# sigaction and sigsetjmp are special. Use special mechanism for
# detecting those, but only if previous attempt failed.
if(HAVE_SIGNAL_H)
@@ -1239,7 +1265,6 @@ foreach(CURL_TEST
HAVE_IN_ADDR_T
HAVE_BOOL_T
STDC_HEADERS
- RETSIGTYPE_TEST
HAVE_INET_NTOA_R_DECL
HAVE_INET_NTOA_R_DECL_REENTRANT
HAVE_GETADDRINFO
@@ -1340,12 +1365,6 @@ if(HAVE_FIONBIO OR
set(HAVE_DISABLED_NONBLOCKING)
endif()
-if(RETSIGTYPE_TEST)
- set(RETSIGTYPE void)
-else()
- set(RETSIGTYPE int)
-endif()
-
if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
include(CheckCCompilerFlag)
check_c_compiler_flag(-Wno-long-double HAVE_C_FLAG_Wno_long_double)
@@ -1383,6 +1402,19 @@ if(WIN32)
# Use the manifest embedded in the Windows Resource
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST")
+
+ # Check if crypto functions in wincrypt.h are actually available
+ if(HAVE_WINCRYPT_H)
+ check_symbol_exists(CryptAcquireContext "${CURL_INCLUDES}" USE_WINCRYPT)
+ endif()
+ if(USE_WINCRYPT)
+ set(USE_WIN32_CRYPTO ON)
+ endif()
+
+ # Link required libraries for USE_WIN32_CRYPTO or USE_SCHANNEL
+ if(USE_WIN32_CRYPTO OR USE_SCHANNEL)
+ list(APPEND CURL_LIBS "advapi32" "crypt32")
+ endif()
endif()
if(MSVC)
@@ -1395,6 +1427,11 @@ if(MSVC)
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
endif()
+
+ # Use multithreaded compilation on VS 2008+
+ if(MSVC_VERSION GREATER_EQUAL 1500)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
+ endif()
endif()
if(CURL_WERROR)
@@ -1479,14 +1516,6 @@ if(BUILD_TESTING)
add_subdirectory(tests)
endif()
-# NTLM support requires crypto function adaptions from various SSL libs
-# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_DARWINSSL OR USE_MBEDTLS OR USE_WIN32_CRYPTO))
- set(use_ntlm ON)
-else()
- set(use_ntlm OFF)
-endif()
-
# Helper to populate a list (_items) with a label when conditions (the remaining
# args) are satisfied
macro(_add_if label)
@@ -1496,6 +1525,13 @@ macro(_add_if label)
endif()
endmacro()
+# NTLM support requires crypto function adaptions from various SSL libs
+# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
+if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_MBEDTLS OR
+ USE_DARWINSSL OR USE_WIN32_CRYPTO))
+ set(use_curl_ntlm_core ON)
+endif()
+
# Clear list and try to detect available features
set(_items)
_add_if("SSL" SSL_ENABLED)
@@ -1505,13 +1541,14 @@ _add_if("libz" HAVE_LIBZ)
_add_if("brotli" HAVE_BROTLI)
_add_if("zstd" HAVE_ZSTD)
_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
-_add_if("IDN" HAVE_LIBIDN2)
-_add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
+_add_if("IDN" HAVE_LIBIDN2 OR USE_WIN32_IDN)
+_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND
((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
# TODO SSP1 (Schannel) check is missing
_add_if("SSPI" USE_WINDOWS_SSPI)
_add_if("GSS-API" HAVE_GSSAPI)
_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
+_add_if("HSTS" NOT CURL_DISABLE_HSTS)
# TODO SSP1 missing for SPNEGO
_add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
@@ -1519,9 +1556,12 @@ _add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-_add_if("NTLM" use_ntlm OR USE_WINDOWS_SSPI)
+_add_if("NTLM" NOT CURL_DISABLE_CRYPTO_AUTH AND
+ (use_curl_ntlm_core OR USE_WINDOWS_SSPI))
# TODO missing option (autoconf: --enable-ntlm-wb)
-_add_if("NTLM_WB" use_ntlm AND NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
+_add_if("NTLM_WB" NOT CURL_DISABLE_CRYPTO_AUTH AND
+ (use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND
+ NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
_add_if("TLS-SRP" USE_TLS_SRP)
# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
@@ -1555,8 +1595,10 @@ _add_if("POP3" NOT CURL_DISABLE_POP3)
_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
_add_if("IMAP" NOT CURL_DISABLE_IMAP)
_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
-_add_if("SMB" NOT CURL_DISABLE_SMB AND use_ntlm)
-_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND use_ntlm)
+_add_if("SMB" NOT CURL_DISABLE_SMB AND
+ use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
+_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND
+ use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
_add_if("SMTP" NOT CURL_DISABLE_SMTP)
_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
_add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH)
@@ -1572,7 +1614,7 @@ message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
# Clear list and collect SSL backends
set(_items)
-_add_if("Schannel" SSL_ENABLED AND USE_WINDOWS_SSPI)
+_add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL)
_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS)
@@ -1677,11 +1719,13 @@ configure_package_config_file(CMake/curl-config.cmake.in
INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
-install(
- EXPORT "${TARGETS_EXPORT_NAME}"
- NAMESPACE "${PROJECT_NAME}::"
- DESTINATION ${CURL_INSTALL_CMAKE_DIR}
-)
+if(CURL_ENABLE_EXPORT_TARGET)
+ install(
+ EXPORT "${TARGETS_EXPORT_NAME}"
+ NAMESPACE "${PROJECT_NAME}::"
+ DESTINATION ${CURL_INSTALL_CMAKE_DIR}
+ )
+endif()
install(
FILES ${version_config} ${project_config}
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index 676dce38e..55a6a39c1 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -155,7 +155,8 @@ typedef enum {
CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
CURLSSLBACKEND_MBEDTLS = 11,
CURLSSLBACKEND_MESALINK = 12,
- CURLSSLBACKEND_BEARSSL = 13
+ CURLSSLBACKEND_BEARSSL = 13,
+ CURLSSLBACKEND_RUSTLS = 14
} curl_sslbackend;
/* aliases for library clones and renames */
@@ -611,6 +612,7 @@ typedef enum {
CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */
CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */
CURLE_PROXY, /* 97 - proxy handshake error */
+ CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */
CURL_LAST /* never use! */
} CURLcode;
@@ -887,6 +889,10 @@ typedef enum {
operating system. Currently implemented under MS-Windows. */
#define CURLSSLOPT_NATIVE_CA (1<<4)
+/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use
+ a client certificate for authentication. (Schannel) */
+#define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5)
+
/* The default connection attempt delay in milliseconds for happy eyeballs.
CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
this value, keep them in sync. */
@@ -1460,8 +1466,8 @@ typedef enum {
#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
/* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
- tell libcurl to resolve names to those IP versions only. This only has
- affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
+ tell libcurl to use those IP versions only. This only has effect on
+ systems with support for more than one, i.e IPv4 _and_ IPv6. */
CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113),
/* Set this option to limit the size of a file that will be downloaded from
@@ -2078,6 +2084,23 @@ typedef enum {
/* Parameters for V4 signature */
CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305),
+ /* Same as CURLOPT_SSL_VERIFYPEER but for DOH (DNS-over-HTTPS) servers. */
+ CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306),
+
+ /* Same as CURLOPT_SSL_VERIFYHOST but for DOH (DNS-over-HTTPS) servers. */
+ CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307),
+
+ /* Same as CURLOPT_SSL_VERIFYSTATUS but for DOH (DNS-over-HTTPS) servers. */
+ CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308),
+
+ /* The CA certificates as "blob" used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+ CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309),
+
+ /* The CA certificates as "blob" used to validate the proxy certificate
+ this option is used only if PROXY_SSL_VERIFYPEER is true */
+ CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2112,10 +2135,10 @@ typedef enum {
/* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
name resolves addresses using more than one IP protocol version, this
option might be handy to force libcurl to use a specific IP version. */
-#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
+#define CURL_IPRESOLVE_WHATEVER 0 /* default, uses addresses to all IP
versions that your system allows */
-#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */
-#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */
+#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 */
#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
@@ -2751,8 +2774,9 @@ typedef enum {
CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57,
CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58,
CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59,
+ CURLINFO_REFERER = CURLINFO_STRING + 60,
- CURLINFO_LASTONE = 59
+ CURLINFO_LASTONE = 60
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2855,6 +2879,7 @@ typedef enum {
CURLVERSION_SEVENTH,
CURLVERSION_EIGHTH,
CURLVERSION_NINTH,
+ CURLVERSION_TENTH,
CURLVERSION_LAST /* never actually use this */
} CURLversion;
@@ -2863,7 +2888,7 @@ typedef enum {
meant to be a built-in version number for what kind of struct the caller
expects. If the struct ever changes, we redefine the NOW to another enum
from above. */
-#define CURLVERSION_NOW CURLVERSION_NINTH
+#define CURLVERSION_NOW CURLVERSION_TENTH
struct curl_version_info_data {
CURLversion age; /* age of the returned struct */
@@ -2916,6 +2941,9 @@ struct curl_version_info_data {
/* These fields were added in CURLVERSION_NINTH */
const char *hyper_version; /* human readable string. */
+
+ /* These fields were added in CURLVERSION_TENTH */
+ const char *gsasl_version; /* human readable string. */
};
typedef struct curl_version_info_data curl_version_info_data;
@@ -2953,6 +2981,7 @@ typedef struct curl_version_info_data curl_version_info_data;
#define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */
#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 */
/*
* NAME curl_version_info()
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 71a64505a..a8d5449af 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -26,16 +26,16 @@
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2020 Daniel Stenberg, <daniel@haxx.se>."
+#define LIBCURL_COPYRIGHT "1996 - 2021 Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.75.0"
+#define LIBCURL_VERSION "7.77.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 75
+#define LIBCURL_VERSION_MINOR 77
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -57,7 +57,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 0x074b00
+#define LIBCURL_VERSION_NUM 0x074d00
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 230f4c106..34d0267ed 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -667,11 +667,11 @@ typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
* this will of course break if we're included before OpenSSL headers...
*/
-typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
-typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
-typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
-typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
- const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX *,
+ const void *);
#else
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
diff --git a/Utilities/cmcurl/lib/CMakeLists.txt b/Utilities/cmcurl/lib/CMakeLists.txt
index 703d0ad02..d8fd7bd30 100644
--- a/Utilities/cmcurl/lib/CMakeLists.txt
+++ b/Utilities/cmcurl/lib/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2021, 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,7 @@
#
###########################################################################
set(LIB_NAME cmcurl)
+set(LIBCURL_OUTPUT_NAME cmcurl)
if(BUILD_SHARED_LIBS)
set(CURL_STATICLIB NO)
@@ -125,7 +126,10 @@ if(WIN32)
endif()
endif()
-set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL)
+set_target_properties(${LIB_NAME} PROPERTIES
+ COMPILE_DEFINITIONS BUILDING_LIBCURL
+ OUTPUT_NAME ${LIBCURL_OUTPUT_NAME}
+ )
if(0) # This code not needed for building within CMake.
if(HIDES_CURL_PRIVATE_SYMBOLS)
@@ -145,13 +149,16 @@ endif()
if(WIN32)
if(BUILD_SHARED_LIBS)
- # Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib"
- set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
+ if(MSVC)
+ # Add "_imp" as a suffix before the extension to avoid conflicting with
+ # the statically linked "libcurl.lib"
+ set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
+ endif()
endif()
endif()
target_include_directories(${LIB_NAME} INTERFACE
- $<INSTALL_INTERFACE:include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
install(TARGETS ${LIB_NAME}
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index e8d2259f2..3e9ddec12 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -25,6 +25,7 @@ LIB_VAUTH_CFILES = \
vauth/cram.c \
vauth/digest.c \
vauth/digest_sspi.c \
+ vauth/gsasl.c \
vauth/krb5_gssapi.c \
vauth/krb5_sspi.c \
vauth/ntlm.c \
@@ -49,6 +50,7 @@ LIB_VTLS_CFILES = \
vtls/mesalink.c \
vtls/nss.c \
vtls/openssl.c \
+ vtls/rustls.c \
vtls/schannel.c \
vtls/schannel_verify.c \
vtls/sectransp.c \
@@ -65,6 +67,7 @@ LIB_VTLS_HFILES = \
vtls/mesalink.h \
vtls/nssg.h \
vtls/openssl.h \
+ vtls/rustls.h \
vtls/schannel.h \
vtls/sectransp.h \
vtls/vtls.h \
@@ -94,6 +97,7 @@ LIB_CFILES = \
asyn-ares.c \
asyn-thread.c \
base64.c \
+ bufref.c \
c-hyper.c \
conncache.c \
connect.c \
@@ -214,6 +218,7 @@ LIB_HFILES = \
amigaos.h \
arpa_telnet.h \
asyn.h \
+ bufref.h \
c-hyper.h \
conncache.h \
connect.h \
diff --git a/Utilities/cmcurl/lib/amigaos.c b/Utilities/cmcurl/lib/amigaos.c
index d3b00d908..78bb22c7e 100644
--- a/Utilities/cmcurl/lib/amigaos.c
+++ b/Utilities/cmcurl/lib/amigaos.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -90,6 +90,33 @@ 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 /* USE_AMISSL */
#endif /* __AMIGA__ */
diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index 2484a7b49..782784735 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -309,7 +309,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
pfd[i].fd = socks[i];
pfd[i].events |= POLLWRNORM|POLLOUT;
}
- if(pfd[i].events != 0)
+ if(pfd[i].events)
num++;
else
break;
@@ -384,13 +384,8 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
them */
res->temp_ai = NULL;
- if(!data->state.async.dns) {
- failf(data, "Could not resolve: %s (%s)",
- data->state.async.hostname,
- ares_strerror(data->state.async.status));
- result = data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
- CURLE_COULDNT_RESOLVE_HOST;
- }
+ if(!data->state.async.dns)
+ result = Curl_resolver_error(data);
else
*dns = data->state.async.dns;
@@ -625,28 +620,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
int *waitp)
{
char *bufp;
- int family = PF_INET;
*waitp = 0; /* default to synchronous response */
-#ifdef ENABLE_IPV6
- switch(data->set.ipver) {
- default:
-#if ARES_VERSION >= 0x010601
- family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
- c-ares versions this just falls through and defaults
- to PF_INET */
- break;
-#endif
- case CURL_IPRESOLVE_V4:
- family = PF_INET;
- break;
- case CURL_IPRESOLVE_V6:
- family = PF_INET6;
- break;
- }
-#endif /* ENABLE_IPV6 */
-
bufp = strdup(hostname);
if(bufp) {
struct thread_data *res = NULL;
@@ -666,33 +642,27 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
/* initial status - failed */
res->last_status = ARES_ENOTFOUND;
-#ifdef ENABLE_IPV6
- if(family == PF_UNSPEC) {
- if(Curl_ipv6works(data)) {
- res->num_pending = 2;
-
- /* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
- PF_INET, query_completed_cb, data);
- ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
- PF_INET6, query_completed_cb, data);
- }
- else {
- res->num_pending = 1;
- /* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
- PF_INET, query_completed_cb, data);
- }
+#if ARES_VERSION >= 0x010601
+ /* IPv6 supported by c-ares since 1.6.1 */
+ if(Curl_ipv6works(data)) {
+ /* The stack seems to be IPv6-enabled */
+ res->num_pending = 2;
+
+ /* areschannel is already setup in the Curl_open() function */
+ ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
+ PF_INET, query_completed_cb, data);
+ ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
+ PF_INET6, query_completed_cb, data);
}
else
-#endif /* ENABLE_IPV6 */
+#endif /* ARES_VERSION >= 0x010601 */
{
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.async.resolver,
- hostname, family,
+ hostname, PF_INET,
query_completed_cb, data);
}
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 9fcbc3c1f..36f68cb49 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -163,7 +163,7 @@ struct thread_sync_data {
int port;
char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
struct Curl_easy *data;
curl_socket_t sock_pair[2]; /* socket pair */
#endif
@@ -201,7 +201,7 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd)
if(tsd->res)
Curl_freeaddrinfo(tsd->res);
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
/*
* close one end of the socket pair (may be done in resolver thread);
* the other end (for reading) is always closed in the parent thread.
@@ -238,12 +238,12 @@ int init_thread_sync_data(struct thread_data *td,
#endif
tsd->mtx = malloc(sizeof(curl_mutex_t));
- if(tsd->mtx == NULL)
+ if(!tsd->mtx)
goto err_exit;
Curl_mutex_init(tsd->mtx);
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
/* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
tsd->sock_pair[0] = CURL_SOCKET_BAD;
@@ -297,7 +297,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
struct thread_data *td = tsd->td;
char service[12];
int rc;
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
char buf[1];
#endif
@@ -305,7 +305,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
- if(rc != 0) {
+ if(rc) {
tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
if(tsd->sock_error == 0)
tsd->sock_error = RESOLVER_ENOMEM;
@@ -322,7 +322,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
free(td);
}
else {
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
/* DNS has been resolved, signal client task */
buf[0] = 1;
@@ -382,7 +382,7 @@ static void destroy_async_data(struct Curl_async *async)
if(async->tdata) {
struct thread_data *td = async->tdata;
int done;
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0];
struct Curl_easy *data = td->tsd.data;
#endif
@@ -407,7 +407,7 @@ static void destroy_async_data(struct Curl_async *async)
free(async->tdata);
}
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
/*
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
@@ -484,35 +484,6 @@ static bool init_resolve_thread(struct Curl_easy *data,
}
/*
- * resolver_error() calls failf() with the appropriate message after a resolve
- * error
- */
-
-static CURLcode resolver_error(struct Curl_easy *data)
-{
- const char *host_or_proxy;
- CURLcode result;
-
-#ifndef CURL_DISABLE_PROXY
- struct connectdata *conn = data->conn;
- if(conn->bits.httpproxy) {
- host_or_proxy = "proxy";
- result = CURLE_COULDNT_RESOLVE_PROXY;
- }
- else
-#endif
- {
- host_or_proxy = "host";
- result = CURLE_COULDNT_RESOLVE_HOST;
- }
-
- failf(data, "Could not resolve %s: %s", host_or_proxy,
- data->state.async.hostname);
-
- return result;
-}
-
-/*
* 'entry' may be NULL and then no data is returned
*/
static CURLcode thread_wait_resolv(struct Curl_easy *data,
@@ -542,7 +513,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
if(!data->state.async.dns && report)
/* a name was not resolved, report error */
- result = resolver_error(data);
+ result = Curl_resolver_error(data);
destroy_async_data(&data->state.async);
@@ -616,7 +587,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
getaddrinfo_complete(data);
if(!data->state.async.dns) {
- CURLcode result = resolver_error(data);
+ CURLcode result = Curl_resolver_error(data);
destroy_async_data(&data->state.async);
return result;
}
@@ -654,13 +625,13 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
timediff_t milli;
timediff_t ms;
struct resdata *reslv = (struct resdata *)data->state.async.resolver;
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
struct thread_data *td = data->state.async.tdata;
#else
(void)socks;
#endif
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
if(td) {
/* return read fd to client for polling the DNS resolution status */
socks[0] = td->tsd.sock_pair[0];
@@ -679,7 +650,7 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
else
milli = 200;
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
-#ifdef USE_SOCKETPAIR
+#ifndef CURL_DISABLE_SOCKETPAIR
}
#endif
@@ -730,24 +701,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* default to synchronous response */
#ifdef CURLRES_IPV6
- /*
- * Check if a limited name resolve has been requested.
- */
- switch(data->set.ipver) {
- case CURL_IPRESOLVE_V4:
- pf = PF_INET;
- break;
- case CURL_IPRESOLVE_V6:
- pf = PF_INET6;
- break;
- default:
+ if(Curl_ipv6works(data))
+ /* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
- break;
- }
-
- if((pf != PF_INET) && !Curl_ipv6works(data))
- /* The stack seems to be a non-IPv6 one */
- pf = PF_INET;
#endif /* CURLRES_IPV6 */
memset(&hints, 0, sizeof(hints));
diff --git a/Utilities/cmcurl/lib/bufref.c b/Utilities/cmcurl/lib/bufref.c
new file mode 100644
index 000000000..b84511e18
--- /dev/null
+++ b/Utilities/cmcurl/lib/bufref.c
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2021, 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 "urldata.h"
+#include "bufref.h"
+
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define SIGNATURE 0x5c48e9b2 /* Random pattern. */
+
+/*
+ * Init a bufref struct.
+ */
+void Curl_bufref_init(struct bufref *br)
+{
+ DEBUGASSERT(br);
+ br->dtor = NULL;
+ br->ptr = NULL;
+ br->len = 0;
+
+#ifdef DEBUGBUILD
+ br->signature = SIGNATURE;
+#endif
+}
+
+/*
+ * Free the buffer and re-init the necessary fields. It doesn't touch the
+ * 'signature' field and thus this buffer reference can be reused.
+ */
+
+void Curl_bufref_free(struct bufref *br)
+{
+ DEBUGASSERT(br);
+ DEBUGASSERT(br->signature == SIGNATURE);
+ DEBUGASSERT(br->ptr || !br->len);
+
+ if(br->ptr && br->dtor)
+ br->dtor((void *) br->ptr);
+
+ br->dtor = NULL;
+ br->ptr = NULL;
+ br->len = 0;
+}
+
+/*
+ * Set the buffer reference to new values. The previously referenced buffer
+ * is released before assignment.
+ */
+void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len,
+ void (*dtor)(void *))
+{
+ DEBUGASSERT(ptr || !len);
+ DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
+
+ Curl_bufref_free(br);
+ br->ptr = (const unsigned char *) ptr;
+ br->len = len;
+ br->dtor = dtor;
+}
+
+/*
+ * Get a pointer to the referenced buffer.
+ */
+const unsigned char *Curl_bufref_ptr(const struct bufref *br)
+{
+ DEBUGASSERT(br);
+ DEBUGASSERT(br->signature == SIGNATURE);
+ DEBUGASSERT(br->ptr || !br->len);
+
+ return br->ptr;
+}
+
+/*
+ * Get the length of the referenced buffer data.
+ */
+size_t Curl_bufref_len(const struct bufref *br)
+{
+ DEBUGASSERT(br);
+ DEBUGASSERT(br->signature == SIGNATURE);
+ DEBUGASSERT(br->ptr || !br->len);
+
+ return br->len;
+}
+
+CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len)
+{
+ unsigned char *cpy = NULL;
+
+ DEBUGASSERT(br);
+ DEBUGASSERT(br->signature == SIGNATURE);
+ DEBUGASSERT(br->ptr || !br->len);
+ DEBUGASSERT(ptr || !len);
+ DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
+
+ if(ptr) {
+ cpy = malloc(len + 1);
+ if(!cpy)
+ return CURLE_OUT_OF_MEMORY;
+ if(len)
+ memcpy(cpy, ptr, len);
+ cpy[len] = '\0';
+ }
+
+ Curl_bufref_set(br, cpy, len, curl_free);
+ return CURLE_OK;
+}
diff --git a/Utilities/cmcurl/lib/bufref.h b/Utilities/cmcurl/lib/bufref.h
new file mode 100644
index 000000000..25f65d894
--- /dev/null
+++ b/Utilities/cmcurl/lib/bufref.h
@@ -0,0 +1,46 @@
+#ifndef HEADER_CURL_BUFREF_H
+#define HEADER_CURL_BUFREF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2021, 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.
+ *
+ ***************************************************************************/
+
+/*
+ * Generic buffer reference.
+ */
+struct bufref {
+ void (*dtor)(void *); /* Associated destructor. */
+ const unsigned char *ptr; /* Referenced data buffer. */
+ size_t len; /* The data size in bytes. */
+#ifdef DEBUGBUILD
+ int signature; /* Detect API use mistakes. */
+#endif
+};
+
+
+void Curl_bufref_init(struct bufref *br);
+void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len,
+ void (*dtor)(void *));
+const unsigned char *Curl_bufref_ptr(const struct bufref *br);
+size_t Curl_bufref_len(const struct bufref *br);
+CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len);
+void Curl_bufref_free(struct bufref *br);
+
+#endif
diff --git a/Utilities/cmcurl/lib/c-hyper.c b/Utilities/cmcurl/lib/c-hyper.c
index 10bd7ef9b..81f589eb9 100644
--- a/Utilities/cmcurl/lib/c-hyper.c
+++ b/Utilities/cmcurl/lib/c-hyper.c
@@ -51,6 +51,7 @@
#include "transfer.h"
#include "multiif.h"
#include "progress.h"
+#include "content_encoding.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -174,8 +175,14 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
}
if(k->ignorebody)
return HYPER_ITER_CONTINUE;
+ if(0 == len)
+ return HYPER_ITER_CONTINUE;
Curl_debug(data, CURLINFO_DATA_IN, buf, len);
- result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
+ if(!data->set.http_ce_skip && k->writer_stack)
+ /* content-encoded data */
+ result = Curl_unencode_write(data, k->writer_stack, buf, len);
+ else
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
if(result) {
data->state.hresult = result;
@@ -198,11 +205,8 @@ static CURLcode status_line(struct Curl_easy *data,
const uint8_t *reason, size_t rlen)
{
CURLcode result;
- size_t wrote;
size_t len;
const char *vstr;
- curl_write_callback writeheader =
- data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
(http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
conn->httpversion =
@@ -225,12 +229,12 @@ static CURLcode status_line(struct Curl_easy *data,
len = Curl_dyn_len(&data->state.headerb);
Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
len);
- Curl_set_in_callback(data, true);
- wrote = writeheader(Curl_dyn_ptr(&data->state.headerb), 1, len,
- data->set.writeheader);
- Curl_set_in_callback(data, false);
- if(wrote != len)
- return CURLE_WRITE_ERROR;
+ result = Curl_client_write(data, CLIENTWRITE_HEADER,
+ Curl_dyn_ptr(&data->state.headerb), len);
+ if(result) {
+ data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
+ return HYPER_ITER_BREAK;
+ }
data->info.header_size += (long)len;
data->req.headerbytecount += (long)len;
@@ -327,7 +331,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
infof(data, "hyperstream is done!\n");
break;
}
- else if(t != HYPER_TASK_RESPONSE) {
+ else if(t != HYPER_TASK_RESPONSE && t != HYPER_TASK_EMPTY) {
*didwhat = KEEP_RECV;
break;
}
@@ -464,8 +468,6 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
else
linelen = 2; /* CRLF ending */
linelen += (p - n);
- if(!n)
- return CURLE_BAD_FUNCTION_ARGUMENT;
vlen = p - v;
if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen,
@@ -741,7 +743,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
- if(data->set.httpversion == CURL_HTTP_VERSION_1_0) {
+ if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
if(HYPERE_OK != hyper_request_set_version(req,
HYPER_HTTP_VERSION_1_0)) {
failf(data, "error setting HTTP version");
@@ -807,14 +809,27 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
#endif
Curl_safefree(data->state.aptr.ref);
- if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
- data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ if(data->state.referer && !Curl_checkheaders(data, "Referer")) {
+ data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
if(!data->state.aptr.ref)
return CURLE_OUT_OF_MEMORY;
if(Curl_hyper_header(data, headers, data->state.aptr.ref))
goto error;
}
+ if(!Curl_checkheaders(data, "Accept-Encoding") &&
+ data->set.str[STRING_ENCODING]) {
+ Curl_safefree(data->state.aptr.accept_encoding);
+ data->state.aptr.accept_encoding =
+ aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
+ if(!data->state.aptr.accept_encoding)
+ return CURLE_OUT_OF_MEMORY;
+ if(Curl_hyper_header(data, headers, data->state.aptr.accept_encoding))
+ goto error;
+ }
+ else
+ Curl_safefree(data->state.aptr.accept_encoding);
+
result = cookies(data, conn, headers);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index 8dfdc0ac8..5453c00f3 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -466,7 +466,6 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
data->state.conn_cache->num_conn--;
DEBUGF(infof(data, "The cache now contains %zu members\n",
data->state.conn_cache->num_conn));
- conn_candidate->data = data; /* associate! */
}
return conn_candidate;
@@ -529,7 +528,6 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
connc->num_conn--;
DEBUGF(infof(data, "The cache now contains %zu members\n",
connc->num_conn));
- conn_candidate->data = data; /* associate! */
}
CONNCACHE_UNLOCK(data);
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index baab1840e..d9317f378 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -171,65 +171,63 @@ singleipconnect(struct Curl_easy *data,
* infinite time left). If the value is negative, the timeout time has already
* elapsed.
*
- * The start time is stored in progress.t_startsingle - as set with
- * Curl_pgrsTime(..., TIMER_STARTSINGLE);
- *
* If 'nowp' is non-NULL, it points to the current time.
* 'duringconnect' is FALSE if not during a connect, as then of course the
* connect timeout is not taken into account!
*
* @unittest: 1303
*/
+
+#define TIMEOUT_CONNECT 1
+#define TIMEOUT_MAXTIME 2
+
timediff_t Curl_timeleft(struct Curl_easy *data,
struct curltime *nowp,
bool duringconnect)
{
- int timeout_set = 0;
- timediff_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
+ unsigned int timeout_set = 0;
+ timediff_t connect_timeout_ms = 0;
+ timediff_t maxtime_timeout_ms = 0;
+ timediff_t timeout_ms = 0;
struct curltime now;
- /* if a timeout is set, use the most restrictive one */
-
- if(data->set.timeout > 0)
- timeout_set |= 1;
- if(duringconnect && (data->set.connecttimeout > 0))
- timeout_set |= 2;
-
- switch(timeout_set) {
- case 1:
- timeout_ms = data->set.timeout;
- break;
- case 2:
- timeout_ms = data->set.connecttimeout;
- break;
- case 3:
- if(data->set.timeout < data->set.connecttimeout)
- timeout_ms = data->set.timeout;
- else
- timeout_ms = data->set.connecttimeout;
- break;
- default:
- /* use the default */
- if(!duringconnect)
- /* if we're not during connect, there's no default timeout so if we're
- at zero we better just return zero and not make it a negative number
- by the math below */
- return 0;
- break;
+ /* The duration of a connect and the total transfer are calculated from two
+ different time-stamps. It can end up with the total timeout being reached
+ before the connect timeout expires and we must acknowledge whichever
+ timeout that is reached first. The total timeout is set per entire
+ operation, while the connect timeout is set per connect. */
+
+ if(data->set.timeout > 0) {
+ timeout_set = TIMEOUT_MAXTIME;
+ maxtime_timeout_ms = data->set.timeout;
+ }
+ if(duringconnect) {
+ timeout_set |= TIMEOUT_CONNECT;
+ connect_timeout_ms = (data->set.connecttimeout > 0) ?
+ data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
}
+ if(!timeout_set)
+ /* no timeout */
+ return 0;
if(!nowp) {
now = Curl_now();
nowp = &now;
}
- /* subtract elapsed time */
- if(duringconnect)
- /* since this most recent connect started */
- timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
- else
- /* since the entire operation started */
- timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
+ if(timeout_set & TIMEOUT_MAXTIME) {
+ maxtime_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
+ timeout_ms = maxtime_timeout_ms;
+ }
+
+ if(timeout_set & TIMEOUT_CONNECT) {
+ connect_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
+
+ if(!(timeout_set & TIMEOUT_MAXTIME) ||
+ (connect_timeout_ms < maxtime_timeout_ms))
+ timeout_ms = connect_timeout_ms;
+ }
+
if(!timeout_ms)
/* avoid returning 0 as that means no timeout! */
return -1;
@@ -611,7 +609,7 @@ static CURLcode trynextip(struct Curl_easy *data,
/* Copies connection info into the transfer handle to make it available when
the transfer handle is no longer associated with the connection. */
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
- char *local_ip, long local_port)
+ char *local_ip, int local_port)
{
memcpy(data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
if(local_ip && local_ip[0])
@@ -627,7 +625,7 @@ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
/* retrieves ip address and port from a sockaddr structure.
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
- char *addr, long *port)
+ char *addr, int *port)
{
struct sockaddr_in *si = NULL;
#ifdef ENABLE_IPV6
@@ -662,7 +660,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
#endif
#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
case AF_UNIX:
- if(salen > (curl_socklen_t)sizeof(sa_family_t)) {
+ if(salen > (curl_socklen_t)sizeof(CURL_SA_FAMILY_T)) {
su = (struct sockaddr_un*)sa;
msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
}
@@ -690,7 +688,7 @@ void Curl_conninfo_remote(struct Curl_easy *data,
char buffer[STRERROR_LEN];
struct Curl_sockaddr_storage ssrem;
curl_socklen_t plen;
- long port;
+ int port;
plen = sizeof(struct Curl_sockaddr_storage);
memset(&ssrem, 0, sizeof(ssrem));
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
@@ -715,7 +713,7 @@ void Curl_conninfo_remote(struct Curl_easy *data,
/* retrieves the start/end point information of a socket of an established
connection */
void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
- char *local_ip, long *local_port)
+ char *local_ip, int *local_port)
{
#ifdef HAVE_GETSOCKNAME
char buffer[STRERROR_LEN];
@@ -752,7 +750,7 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
ip address and port number whenever an outgoing connection is
**established** from the primary socket to a remote address. */
char local_ip[MAX_IPADR_LEN] = "";
- long local_port = -1;
+ int local_port = -1;
if(conn->transport == TRNSPRT_TCP) {
if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
@@ -908,8 +906,10 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
connkeep(conn, "HTTP/3 default");
return CURLE_OK;
}
- if(result)
+ if(result) {
+ conn->tempsock[i] = CURL_SOCKET_BAD;
error = SOCKERRNO;
+ }
}
else
#endif
@@ -1158,7 +1158,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
curl_socket_t sockfd;
CURLcode result;
char ipaddress[MAX_IPADR_LEN];
- long port;
+ int port;
bool is_tcp;
#ifdef TCP_FASTOPEN_CONNECT
int optval = 1;
@@ -1180,7 +1180,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
Curl_closesocket(data, conn, sockfd);
return CURLE_OK;
}
- infof(data, " Trying %s:%ld...\n", ipaddress, port);
+ infof(data, " Trying %s:%d...\n", ipaddress, port);
#ifdef ENABLE_IPV6
is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
@@ -1367,14 +1367,31 @@ CURLcode Curl_connecthost(struct Curl_easy *data,
conn->timeoutms_per_addr[1] =
conn->tempaddr[1]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
- conn->tempfamily[0] = conn->tempaddr[0]?
- conn->tempaddr[0]->ai_family:0;
+ if(conn->ip_version == CURL_IPRESOLVE_WHATEVER) {
+ /* any IP version is allowed */
+ conn->tempfamily[0] = conn->tempaddr[0]?
+ conn->tempaddr[0]->ai_family:0;
+#ifdef ENABLE_IPV6
+ conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ?
+ AF_INET : AF_INET6;
+#else
+ conn->tempfamily[1] = AF_UNSPEC;
+#endif
+ }
+ else {
+ /* only one IP version is allowed */
+ conn->tempfamily[0] = (conn->ip_version == CURL_IPRESOLVE_V4) ?
+ AF_INET :
#ifdef ENABLE_IPV6
- conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ?
- AF_INET : AF_INET6;
+ AF_INET6;
#else
- conn->tempfamily[1] = AF_UNSPEC;
+ AF_UNSPEC;
#endif
+ conn->tempfamily[1] = AF_UNSPEC;
+
+ ainext(conn, 0, FALSE); /* find first address of the right type */
+ }
+
ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */
DEBUGF(infof(data, "family0 == %s, family1 == %s\n",
@@ -1448,11 +1465,9 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
}
c = find.found;
- if(connp) {
+ if(connp)
/* only store this if the caller cares for it */
*connp = c;
- c->data = data;
- }
return c->sock[FIRSTSOCKET];
}
return CURL_SOCKET_BAD;
diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h
index 566b3531d..1a055f58d 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -54,7 +54,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp);
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
- char *addr, long *port);
+ char *addr, int *port);
/*
* Check if a connection seems to be alive.
@@ -81,9 +81,9 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
void Curl_conninfo_remote(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sockfd);
void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
- char *local_ip, long *local_port);
+ char *local_ip, int *local_port);
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
- char *local_ip, long local_port);
+ char *local_ip, int local_port);
int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sock);
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index f179b8179..a84ff543b 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/lib/content_encoding.c
@@ -178,7 +178,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
/* Dynamically allocate a buffer for decompression because it's uncommonly
large to hold on the stack */
decomp = malloc(DSIZ);
- if(decomp == NULL)
+ if(!decomp)
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
/* because the buffer size is fixed, iteratively decompress and transfer to
@@ -487,7 +487,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
*/
z->avail_in = (uInt) nbytes;
z->next_in = malloc(z->avail_in);
- if(z->next_in == NULL) {
+ if(!z->next_in) {
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
}
memcpy(z->next_in, buf, z->avail_in);
@@ -509,7 +509,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
ssize_t hlen;
z->avail_in += (uInt) nbytes;
z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
- if(z->next_in == NULL) {
+ if(!z->next_in) {
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* Append the new block of data to the previous one */
@@ -985,7 +985,8 @@ new_unencoding_writer(struct Curl_easy *data,
return writer;
}
-/* Write data using an unencoding writer stack. */
+/* Write data using an unencoding writer stack. "nbytes" is not
+ allowed to be 0. */
CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 09fd092ac..941623f9d 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -105,6 +105,8 @@ Example set of cookies:
#include "curl_memory.h"
#include "memdebug.h"
+static void strstore(char **str, const char *newstr);
+
static void freecookie(struct Cookie *co)
{
free(co->expirestr);
@@ -129,12 +131,13 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len))
return FALSE;
- /* A lead char of cookie_domain is not '.'.
- RFC6265 4.1.2.3. The Domain Attribute says:
- For example, if the value of the Domain attribute is
- "example.com", the user agent will include the cookie in the Cookie
- header when making HTTP requests to example.com, www.example.com, and
- www.corp.example.com.
+ /*
+ * A lead char of cookie_domain is not '.'.
+ * RFC6265 4.1.2.3. The Domain Attribute says:
+ * For example, if the value of the Domain attribute is
+ * "example.com", the user agent will include the cookie in the Cookie
+ * header when making HTTP requests to example.com, www.example.com, and
+ * www.corp.example.com.
*/
if(hostname_len == cookie_domain_len)
return TRUE;
@@ -144,7 +147,10 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
}
/*
- * Return true if the given string is an IP(v4|v6) address.
+ * isip
+ *
+ * Returns true if the given string is an IPv4 or IPv6 address (if IPv6 has
+ * been enabled while building libcurl, and false otherwise.
*/
static bool isip(const char *domain)
{
@@ -193,19 +199,19 @@ static bool pathmatch(const char *cookie_path, const char *request_uri)
/* #-fragments are already cut off! */
if(0 == strlen(uri_path) || uri_path[0] != '/') {
- free(uri_path);
- uri_path = strdup("/");
+ strstore(&uri_path, "/");
if(!uri_path)
return FALSE;
}
- /* here, RFC6265 5.1.4 says
- 4. Output the characters of the uri-path from the first character up
- to, but not including, the right-most %x2F ("/").
- but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
- without redirect.
- Ignore this algorithm because /hoge is uri path for this case
- (uri path is not /).
+ /*
+ * here, RFC6265 5.1.4 says
+ * 4. Output the characters of the uri-path from the first character up
+ * to, but not including, the right-most %x2F ("/").
+ * but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
+ * without redirect.
+ * Ignore this algorithm because /hoge is uri path for this case
+ * (uri path is not /).
*/
uri_path_len = strlen(uri_path);
@@ -328,8 +334,7 @@ static char *sanitize_cookie_path(const char *cookie_path)
/* RFC6265 5.2.4 The Path Attribute */
if(new_path[0] != '/') {
/* Let cookie-path be the default-path. */
- free(new_path);
- new_path = strdup("/");
+ strstore(&new_path, "/");
return new_path;
}
@@ -348,7 +353,7 @@ static char *sanitize_cookie_path(const char *cookie_path)
*/
void Curl_cookie_loadfiles(struct Curl_easy *data)
{
- struct curl_slist *list = data->change.cookielist;
+ struct curl_slist *list = data->state.cookielist;
if(list) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
while(list) {
@@ -357,7 +362,8 @@ void Curl_cookie_loadfiles(struct Curl_easy *data)
data->cookies,
data->set.cookiesession);
if(!newcookies)
- /* Failure may be due to OOM or a bad cookie; both are ignored
+ /*
+ * Failure may be due to OOM or a bad cookie; both are ignored
* but only the first should be
*/
infof(data, "ignoring failed cookie_init for %s\n", list->data);
@@ -365,17 +371,20 @@ void Curl_cookie_loadfiles(struct Curl_easy *data)
data->cookies = newcookies;
list = list->next;
}
- curl_slist_free_all(data->change.cookielist); /* clean up list */
- data->change.cookielist = NULL; /* don't do this again! */
+ curl_slist_free_all(data->state.cookielist); /* clean up list */
+ data->state.cookielist = NULL; /* don't do this again! */
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
}
/*
- * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL
- * that will be freed before the allocated string is stored there.
+ * strstore
*
- * It is meant to easily replace strdup()
+ * A thin wrapper around strdup which ensures that any memory allocated at
+ * *str will be freed before the string allocated by strdup is stored there.
+ * The intended usecase is repeated assignments to the same variable during
+ * parsing in a last-wins scenario. The caller is responsible for checking
+ * for OOM errors.
*/
static void strstore(char **str, const char *newstr)
{
@@ -384,7 +393,11 @@ static void strstore(char **str, const char *newstr)
}
/*
- * remove_expired() removes expired cookies.
+ * remove_expired
+ *
+ * Remove expired cookies from the hash by inspecting the expires timestamp on
+ * each cookie in the hash, freeing and deleting any where the timestamp is in
+ * the past.
*/
static void remove_expired(struct CookieInfo *cookies)
{
@@ -421,25 +434,23 @@ static bool bad_domain(const char *domain)
return !strchr(domain, '.') && !strcasecompare(domain, "localhost");
}
-/****************************************************************************
- *
- * Curl_cookie_add()
- *
- * Add a single cookie line to the cookie keeping object.
+/*
+ * Curl_cookie_add
*
- * Be aware that sometimes we get an IP-only host name, and that might also be
- * a numerical IPv6 address.
+ * Add a single cookie line to the cookie keeping object. Be aware that
+ * sometimes we get an IP-only host name, and that might also be a numerical
+ * IPv6 address.
*
* Returns NULL on out of memory or invalid cookie. This is suboptimal,
* as they should be treated separately.
- ***************************************************************************/
-
+ */
struct Cookie *
Curl_cookie_add(struct Curl_easy *data,
- /* The 'data' pointer here may be NULL at times, and thus
- must only be used very carefully for things that can deal
- with data being NULL. Such as infof() and similar */
-
+ /*
+ * The 'data' pointer here may be NULL at times, and thus
+ * must only be used very carefully for things that can deal
+ * with data being NULL. Such as infof() and similar
+ */
struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */
bool noexpire, /* if TRUE, skip remove_expired() */
@@ -493,9 +504,11 @@ Curl_cookie_add(struct Curl_easy *data,
if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%"
MAX_NAME_TXT "[^;\r\n]",
name, what)) {
- /* Use strstore() below to properly deal with received cookie
- headers that have the same string property set more than once,
- and then we use the last one. */
+ /*
+ * Use strstore() below to properly deal with received cookie
+ * headers that have the same string property set more than once,
+ * and then we use the last one.
+ */
const char *whatptr;
bool done = FALSE;
bool sep;
@@ -503,11 +516,13 @@ Curl_cookie_add(struct Curl_easy *data,
size_t nlen = strlen(name);
const char *endofn = &ptr[ nlen ];
+ /*
+ * Check for too long individual name or contents, or too long
+ * combination of name + contents. Chrome and Firefox support 4095 or
+ * 4096 bytes combo
+ */
if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
((nlen + len) > MAX_NAME)) {
- /* too long individual name or contents, or too long combination of
- name + contents. Chrome and Firefox support 4095 or 4096 bytes
- combo. */
freecookie(co);
infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n",
nlen, len);
@@ -569,8 +584,10 @@ Curl_cookie_add(struct Curl_easy *data,
}
}
else if(!len) {
- /* this was a "<name>=" with no content, and we must allow
- 'secure' and 'httponly' specified this weirdly */
+ /*
+ * this was a "<name>=" with no content, and we must allow
+ * 'secure' and 'httponly' specified this weirdly
+ */
done = TRUE;
/*
* secure cookies are only allowed to be set when the connection is
@@ -610,8 +627,10 @@ Curl_cookie_add(struct Curl_easy *data,
else if(strcasecompare("domain", name)) {
bool is_ip;
- /* Now, we make sure that our host is within the given domain,
- or the given domain is not valid and thus cannot be set. */
+ /*
+ * Now, we make sure that our host is within the given domain, or
+ * the given domain is not valid and thus cannot be set.
+ */
if('.' == whatptr[0])
whatptr++; /* ignore preceding dot */
@@ -641,9 +660,10 @@ Curl_cookie_add(struct Curl_easy *data,
given */
}
else {
- /* we did not get a tailmatch and then the attempted set domain
- is not a domain to which the current host belongs. Mark as
- bad. */
+ /*
+ * We did not get a tailmatch and then the attempted set domain is
+ * not a domain to which the current host belongs. Mark as bad.
+ */
badcookie = TRUE;
infof(data, "skipped cookie with bad tailmatch domain: %s\n",
whatptr);
@@ -657,15 +677,15 @@ Curl_cookie_add(struct Curl_easy *data,
}
}
else if(strcasecompare("max-age", name)) {
- /* Defined in RFC2109:
-
- Optional. The Max-Age attribute defines the lifetime of the
- cookie, in seconds. The delta-seconds value is a decimal non-
- negative integer. After delta-seconds seconds elapse, the
- client should discard the cookie. A value of zero means the
- cookie should be discarded immediately.
-
- */
+ /*
+ * Defined in RFC2109:
+ *
+ * Optional. The Max-Age attribute defines the lifetime of the
+ * cookie, in seconds. The delta-seconds value is a decimal non-
+ * negative integer. After delta-seconds seconds elapse, the
+ * client should discard the cookie. A value of zero means the
+ * cookie should be discarded immediately.
+ */
strstore(&co->maxage, whatptr);
if(!co->maxage) {
badcookie = TRUE;
@@ -679,9 +699,10 @@ Curl_cookie_add(struct Curl_easy *data,
break;
}
}
+
/*
- else this is the second (or more) name we don't know
- about! */
+ * Else, this is the second (or more) name we don't know about!
+ */
}
else {
/* this is an "illegal" <what>=<this> pair */
@@ -699,8 +720,10 @@ Curl_cookie_add(struct Curl_easy *data,
semiptr = strchr(ptr, ';'); /* now, find the next semicolon */
if(!semiptr && *ptr)
- /* There are no more semicolons, but there's a final name=value pair
- coming up */
+ /*
+ * There are no more semicolons, but there's a final name=value pair
+ * coming up
+ */
semiptr = strchr(ptr, '\0');
} while(semiptr);
@@ -724,13 +747,16 @@ Curl_cookie_add(struct Curl_easy *data,
}
}
else if(co->expirestr) {
- /* Note that if the date couldn't get parsed for whatever reason,
- the cookie will be treated as a session cookie */
+ /*
+ * Note that if the date couldn't get parsed for whatever reason, the
+ * cookie will be treated as a session cookie
+ */
co->expires = Curl_getdate_capped(co->expirestr);
- /* Session cookies have expires set to 0 so if we get that back
- from the date parser let's add a second to make it a
- non-session cookie */
+ /*
+ * Session cookies have expires set to 0 so if we get that back from the
+ * date parser let's add a second to make it a non-session cookie
+ */
if(co->expires == 0)
co->expires = 1;
else if(co->expires < 0)
@@ -747,13 +773,17 @@ Curl_cookie_add(struct Curl_easy *data,
}
if(!badcookie && !co->path && path) {
- /* No path was given in the header line, set the default.
- Note that the passed-in path to this function MAY have a '?' and
- following part that MUST not be stored as part of the path. */
+ /*
+ * No path was given in the header line, set the default. Note that the
+ * passed-in path to this function MAY have a '?' and following part that
+ * MUST NOT be stored as part of the path.
+ */
char *queryp = strchr(path, '?');
- /* queryp is where the interesting part of the path ends, so now we
- want to the find the last */
+ /*
+ * queryp is where the interesting part of the path ends, so now we
+ * want to the find the last
+ */
char *endslash;
if(!queryp)
endslash = strrchr(path, '/');
@@ -774,29 +804,34 @@ Curl_cookie_add(struct Curl_easy *data,
}
}
+ /*
+ * If we didn't get a cookie name, or a bad one, the this is an illegal
+ * line so bail out.
+ */
if(badcookie || !co->name) {
- /* we didn't get a cookie name or a bad one,
- this is an illegal line, bail out */
freecookie(co);
return NULL;
}
}
else {
- /* This line is NOT a HTTP header style line, we do offer support for
- reading the odd netscape cookies-file format here */
+ /*
+ * This line is NOT a HTTP header style line, we do offer support for
+ * reading the odd netscape cookies-file format here
+ */
char *ptr;
char *firstptr;
char *tok_buf = NULL;
int fields;
- /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies
- marked with httpOnly after the domain name are not accessible
- from javascripts, but since curl does not operate at javascript
- level, we include them anyway. In Firefox's cookie files, these
- lines are preceded with #HttpOnly_ and then everything is
- as usual, so we skip 10 characters of the line..
- */
+ /*
+ * IE introduced HTTP-only cookies to prevent XSS attacks. Cookies marked
+ * with httpOnly after the domain name are not accessible from javascripts,
+ * but since curl does not operate at javascript level, we include them
+ * anyway. In Firefox's cookie files, these lines are preceded with
+ * #HttpOnly_ and then everything is as usual, so we skip 10 characters of
+ * the line..
+ */
if(strncmp(lineptr, "#HttpOnly_", 10) == 0) {
lineptr += 10;
co->httponly = TRUE;
@@ -817,8 +852,10 @@ Curl_cookie_add(struct Curl_easy *data,
firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
- /* Now loop through the fields and init the struct we already have
- allocated */
+ /*
+ * Now loop through the fields and init the struct we already have
+ * allocated
+ */
for(ptr = firstptr, fields = 0; ptr && !badcookie;
ptr = strtok_r(NULL, "\t", &tok_buf), fields++) {
switch(fields) {
@@ -830,10 +867,11 @@ Curl_cookie_add(struct Curl_easy *data,
badcookie = TRUE;
break;
case 1:
- /* flag: A TRUE/FALSE value indicating if all machines within a given
- domain can access the variable. Set TRUE when the cookie says
- .domain.com and to false when the domain is complete www.domain.com
- */
+ /*
+ * flag: A TRUE/FALSE value indicating if all machines within a given
+ * domain can access the variable. Set TRUE when the cookie says
+ * .domain.com and to false when the domain is complete www.domain.com
+ */
co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
break;
case 2:
@@ -942,17 +980,23 @@ Curl_cookie_add(struct Curl_easy *data,
co->livecookie = c->running;
co->creationtime = ++c->lastct;
- /* now, we have parsed the incoming line, we must now check if this
- supersedes an already existing cookie, which it may if the previous have
- the same domain and path as this */
+ /*
+ * Now we have parsed the incoming line, we must now check if this supersedes
+ * an already existing cookie, which it may if the previous have the same
+ * domain and path as this.
+ */
/* at first, remove expired cookies */
if(!noexpire)
remove_expired(c);
#ifdef USE_LIBPSL
- /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */
- if(domain && co->domain && !isip(co->domain)) {
+ /*
+ * Check if the domain is a Public Suffix and if yes, ignore the cookie. We
+ * must also check that the data handle isn't NULL since the psl code will
+ * dereference it.
+ */
+ if(data && (domain && co->domain && !isip(co->domain))) {
const psl_ctx_t *psl = Curl_psl_use(data);
int acceptable;
@@ -1028,12 +1072,12 @@ Curl_cookie_add(struct Curl_easy *data,
}
if(replace_old && !co->livecookie && clist->livecookie) {
- /* Both cookies matched fine, except that the already present
- cookie is "live", which means it was set from a header, while
- the new one isn't "live" and thus only read from a file. We let
- live cookies stay alive */
-
- /* Free the newcomer and get out of here! */
+ /*
+ * Both cookies matched fine, except that the already present cookie is
+ * "live", which means it was set from a header, while the new one was
+ * read from a file and thus isn't "live". "live" cookies are preferred
+ * so the new cookie is freed.
+ */
freecookie(co);
return NULL;
}
@@ -1059,8 +1103,10 @@ Curl_cookie_add(struct Curl_easy *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 */
+ /*
+ * 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;
@@ -1092,19 +1138,19 @@ Curl_cookie_add(struct Curl_easy *data,
}
-/*****************************************************************************
- *
+/*
* Curl_cookie_init()
*
* Inits a cookie struct to read data from a local file. This is always
- * called before any cookies are set. File may be NULL.
+ * called before any cookies are set. File may be NULL in which case only the
+ * struct is initialized. Is file is "-" then STDIN is read.
*
* If 'newsession' is TRUE, discard all "session cookies" on read from file.
*
* Note that 'data' might be called as NULL pointer.
*
* Returns NULL on out of memory. Invalid cookies are ignored.
- ****************************************************************************/
+ */
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
const char *file,
struct CookieInfo *inc,
@@ -1166,7 +1212,12 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
}
free(line); /* free the line buffer */
- remove_expired(c); /* run this once, not on every cookie */
+
+ /*
+ * Remove expired cookies from the hash. We must make sure to run this
+ * after reading the file, and not not on every cookie.
+ */
+ remove_expired(c);
if(fromfile)
fclose(fp);
@@ -1180,16 +1231,24 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
fail:
free(line);
+ /*
+ * Only clean up if we allocated it here, as the original could still be in
+ * use by a share handle.
+ */
if(!inc)
- /* Only clean up if we allocated it here, as the original could still be in
- * use by a share handle */
Curl_cookie_cleanup(c);
if(fromfile && fp)
fclose(fp);
return NULL; /* out of memory */
}
-/* sort this so that the longest path gets before the shorter path */
+/*
+ * cookie_sort
+ *
+ * Helper function to sort cookies such that the longest path gets before the
+ * shorter path. Path, domain and name lengths are considered in that order,
+ * with tge creationtime as the tiebreaker.
+ */
static int cookie_sort(const void *p1, const void *p2)
{
struct Cookie *c1 = *(struct Cookie **)p1;
@@ -1221,7 +1280,11 @@ static int cookie_sort(const void *p1, const void *p2)
return (c2->creationtime > c1->creationtime) ? 1 : -1;
}
-/* sort cookies only according to creation time */
+/*
+ * cookie_sort_ct
+ *
+ * Helper function to sort cookies according to creation time.
+ */
static int cookie_sort_ct(const void *p1, const void *p2)
{
struct Cookie *c1 = *(struct Cookie **)p1;
@@ -1265,18 +1328,15 @@ static struct Cookie *dup_cookie(struct Cookie *src)
return NULL;
}
-/*****************************************************************************
- *
- * Curl_cookie_getlist()
+/*
+ * Curl_cookie_getlist
*
- * For a given host and path, return a linked list of cookies that the
- * client should send to the server if used now. The secure boolean informs
- * the cookie if a secure connection is achieved or not.
+ * For a given host and path, return a linked list of cookies that the client
+ * should send to the server if used now. The secure boolean informs the cookie
+ * if a secure connection is achieved or not.
*
* It shall only return cookies that haven't expired.
- *
- ****************************************************************************/
-
+ */
struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
const char *host, const char *path,
bool secure)
@@ -1307,15 +1367,21 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
if(!co->domain ||
(co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) {
- /* the right part of the host matches the domain stuff in the
- cookie data */
+ /*
+ * the right part of the host matches the domain stuff in the
+ * cookie data
+ */
- /* now check the left part of the path with the cookies path
- requirement */
+ /*
+ * now check the left part of the path with the cookies path
+ * requirement
+ */
if(!co->spath || pathmatch(co->spath, path) ) {
- /* and now, we know this is a match and we should create an
- entry for the return-linked-list */
+ /*
+ * and now, we know this is a match and we should create an
+ * entry for the return-linked-list
+ */
newco = dup_cookie(co);
if(newco) {
@@ -1336,9 +1402,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
}
if(matches) {
- /* Now we need to make sure that if there is a name appearing more than
- once, the longest specified path version comes first. To make this
- the swiftest way, we just sort them all based on path length. */
+ /*
+ * Now we need to make sure that if there is a name appearing more than
+ * once, the longest specified path version comes first. To make this
+ * the swiftest way, we just sort them all based on path length.
+ */
struct Cookie **array;
size_t i;
@@ -1373,13 +1441,11 @@ fail:
return NULL;
}
-/*****************************************************************************
- *
- * Curl_cookie_clearall()
+/*
+ * Curl_cookie_clearall
*
* Clear all existing cookies and reset the counter.
- *
- ****************************************************************************/
+ */
void Curl_cookie_clearall(struct CookieInfo *cookies)
{
if(cookies) {
@@ -1392,14 +1458,11 @@ void Curl_cookie_clearall(struct CookieInfo *cookies)
}
}
-/*****************************************************************************
- *
- * Curl_cookie_freelist()
+/*
+ * Curl_cookie_freelist
*
* Free a list of cookies previously returned by Curl_cookie_getlist();
- *
- ****************************************************************************/
-
+ */
void Curl_cookie_freelist(struct Cookie *co)
{
struct Cookie *next;
@@ -1410,14 +1473,11 @@ void Curl_cookie_freelist(struct Cookie *co)
}
}
-
-/*****************************************************************************
- *
- * Curl_cookie_clearsess()
+/*
+ * Curl_cookie_clearsess
*
* Free all session cookies in the cookies list.
- *
- ****************************************************************************/
+ */
void Curl_cookie_clearsess(struct CookieInfo *cookies)
{
struct Cookie *first, *curr, *next, *prev = NULL;
@@ -1454,14 +1514,11 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies)
}
}
-
-/*****************************************************************************
- *
+/*
* Curl_cookie_cleanup()
*
* Free a "cookie object" previous created with Curl_cookie_init().
- *
- ****************************************************************************/
+ */
void Curl_cookie_cleanup(struct CookieInfo *c)
{
if(c) {
@@ -1473,12 +1530,13 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
}
}
-/* get_netscape_format()
+/*
+ * get_netscape_format()
*
* Formats a string for Netscape output file, w/o a newline at the end.
- *
- * Function returns a char * to a formatted line. Has to be free()d
-*/
+ * Function returns a char * to a formatted line. The caller is responsible
+ * for freeing the returned pointer.
+ */
static char *get_netscape_format(const struct Cookie *co)
{
return aprintf(
@@ -1491,8 +1549,10 @@ static char *get_netscape_format(const struct Cookie *co)
"%s\t" /* name */
"%s", /* value */
co->httponly?"#HttpOnly_":"",
- /* Make sure all domains are prefixed with a dot if they allow
- tailmatching. This is Mozilla-style. */
+ /*
+ * Make sure all domains are prefixed with a dot if they allow
+ * tailmatching. This is Mozilla-style.
+ */
(co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
co->domain?co->domain:"unknown",
co->tailmatch?"TRUE":"FALSE",
@@ -1511,18 +1571,18 @@ static char *get_netscape_format(const struct Cookie *co)
*
* The function returns non-zero on write failure.
*/
-static int cookie_output(struct Curl_easy *data,
- struct CookieInfo *c, const char *filename)
+static CURLcode cookie_output(struct Curl_easy *data,
+ struct CookieInfo *c, const char *filename)
{
struct Cookie *co;
FILE *out = NULL;
bool use_stdout = FALSE;
char *tempstore = NULL;
- bool error = false;
+ CURLcode error = CURLE_OK;
if(!c)
/* no cookie engine alive */
- return 0;
+ return CURLE_OK;
/* at first, remove expired cookies */
remove_expired(c);
@@ -1540,11 +1600,13 @@ static int cookie_output(struct Curl_easy *data,
tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
if(!tempstore)
- return 1;
+ return CURLE_OUT_OF_MEMORY;
out = fopen(tempstore, FOPEN_WRITETEXT);
- if(!out)
+ if(!out) {
+ error = CURLE_WRITE_ERROR;
goto error;
+ }
}
fputs("# Netscape HTTP Cookie File\n"
@@ -1559,6 +1621,7 @@ static int cookie_output(struct Curl_easy *data,
array = calloc(1, sizeof(struct Cookie *) * c->numcookies);
if(!array) {
+ error = CURLE_OUT_OF_MEMORY;
goto error;
}
@@ -1575,9 +1638,9 @@ static int cookie_output(struct Curl_easy *data,
for(i = 0; i < nvalid; i++) {
char *format_ptr = get_netscape_format(array[i]);
- if(format_ptr == NULL) {
- fprintf(out, "#\n# Fatal libcurl error\n");
+ if(!format_ptr) {
free(array);
+ error = CURLE_OUT_OF_MEMORY;
goto error;
}
fprintf(out, "%s\n", format_ptr);
@@ -1592,18 +1655,24 @@ static int cookie_output(struct Curl_easy *data,
out = NULL;
if(Curl_rename(tempstore, filename)) {
unlink(tempstore);
+ error = CURLE_WRITE_ERROR;
goto error;
}
}
- goto cleanup;
+ /*
+ * If we reach here we have successfully written a cookie file so theree is
+ * no need to inspect the error, any error case should have jumped into the
+ * error block below.
+ */
+ free(tempstore);
+ return CURLE_OK;
+
error:
- error = true;
-cleanup:
if(out && !use_stdout)
fclose(out);
free(tempstore);
- return error ? 1 : 0;
+ return error;
}
static struct curl_slist *cookie_list(struct Curl_easy *data)
@@ -1614,8 +1683,7 @@ static struct curl_slist *cookie_list(struct Curl_easy *data)
char *line;
unsigned int i;
- if((data->cookies == NULL) ||
- (data->cookies->numcookies == 0))
+ if(!data->cookies || (data->cookies->numcookies == 0))
return NULL;
for(i = 0; i < COOKIE_HASH_SIZE; i++) {
@@ -1651,8 +1719,10 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
void Curl_flush_cookies(struct Curl_easy *data, bool cleanup)
{
+ CURLcode res;
+
if(data->set.str[STRING_COOKIEJAR]) {
- if(data->change.cookielist) {
+ if(data->state.cookielist) {
/* If there is a list of cookie files to read, do it first so that
we have all the told files read before we write the new jar.
Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */
@@ -1662,16 +1732,17 @@ void Curl_flush_cookies(struct Curl_easy *data, bool cleanup)
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
/* if we have a destination file for all the cookies to get dumped to */
- if(cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]))
- infof(data, "WARNING: failed to save cookies in %s\n",
- data->set.str[STRING_COOKIEJAR]);
+ res = cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]);
+ if(res)
+ infof(data, "WARNING: failed to save cookies in %s: %s\n",
+ data->set.str[STRING_COOKIEJAR], curl_easy_strerror(res));
}
else {
- if(cleanup && data->change.cookielist) {
+ if(cleanup && data->state.cookielist) {
/* since nothing is written, we can just free the list of cookie file
names */
- curl_slist_free_all(data->change.cookielist); /* clean up list */
- data->change.cookielist = NULL;
+ curl_slist_free_all(data->state.cookielist); /* clean up list */
+ data->state.cookielist = NULL;
}
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
}
diff --git a/Utilities/cmcurl/lib/cookie.h b/Utilities/cmcurl/lib/cookie.h
index e0aa383be..460bbb104 100644
--- a/Utilities/cmcurl/lib/cookie.h
+++ b/Utilities/cmcurl/lib/cookie.h
@@ -91,13 +91,13 @@ struct Curl_easy;
*/
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
- struct CookieInfo *, bool header, bool noexpiry,
- char *lineptr,
+ struct CookieInfo *c, bool header,
+ bool noexpiry, char *lineptr,
const char *domain, const char *path,
bool secure);
-struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
- const char *, bool);
+struct Cookie *Curl_cookie_getlist(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);
void Curl_cookie_clearsess(struct CookieInfo *cookies);
@@ -110,9 +110,10 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies);
#define Curl_flush_cookies(x,y) Curl_nop_stmt
#else
void Curl_flush_cookies(struct Curl_easy *data, bool cleanup);
-void Curl_cookie_cleanup(struct CookieInfo *);
+void Curl_cookie_cleanup(struct CookieInfo *c);
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
- const char *, struct CookieInfo *, bool);
+ const char *file, struct CookieInfo *inc,
+ bool newsession);
struct curl_slist *Curl_cookie_list(struct Curl_easy *data);
void Curl_cookie_loadfiles(struct Curl_easy *data);
#endif
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 06537b275..1d5067bc0 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -50,6 +50,12 @@
# define in_addr_t unsigned long
#endif
+#if defined(USE_UNIX_SOCKETS) && defined(WINAPI_FAMILY) && \
+ (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+ /* Required for sockaddr_un type */
+# include <afunix.h>
+#endif
+
#include <stddef.h>
#include "curl_addrinfo.h"
@@ -141,7 +147,7 @@ Curl_getaddrinfo_ex(const char *nodename,
continue;
/* ignore elements without required address info */
- if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0))
+ if(!ai->ai_addr || !(ai->ai_addrlen > 0))
continue;
/* ignore elements with bogus address size */
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index 8dfe3285c..4fdc672a0 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -91,7 +91,7 @@
#endif
/* Allow SMB to work on Windows */
-#cmakedefine USE_WIN32_CRYPTO
+#cmakedefine USE_WIN32_CRYPTO 1
/* Use Windows LDAP implementation */
#cmakedefine USE_WIN32_LDAP 1
@@ -105,21 +105,6 @@
/* Define if you want to enable IPv6 support */
#cmakedefine ENABLE_IPV6 1
-/* Define to the type qualifier of arg 1 for getnameinfo. */
-#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1}
-
-/* Define to the type of arg 1 for getnameinfo. */
-#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1}
-
-/* Define to the type of arg 2 for getnameinfo. */
-#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2}
-
-/* Define to the type of args 4 and 6 for getnameinfo. */
-#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46}
-
-/* Define to the type of arg 7 for getnameinfo. */
-#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7}
-
/* Specifies the number of arguments to getservbyport_r */
#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS}
@@ -201,6 +186,9 @@
/* 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 gethostbyaddr function. */
#cmakedefine HAVE_GETHOSTBYADDR 1
@@ -237,9 +225,6 @@
/* Define to 1 if you have a working getifaddrs function. */
#cmakedefine HAVE_GETIFADDRS 1
-/* Define to 1 if you have the getnameinfo function. */
-#cmakedefine HAVE_GETNAMEINFO 1
-
/* Define to 1 if you have the `getpass_r' function. */
#cmakedefine HAVE_GETPASS_R 1
@@ -315,21 +300,18 @@
/* Define to 1 if you have the `inet_addr' function. */
#cmakedefine HAVE_INET_ADDR 1
-/* Define to 1 if you have the inet_ntoa_r function. */
-#cmakedefine HAVE_INET_NTOA_R 1
-
-/* inet_ntoa_r() takes 2 args */
-#cmakedefine HAVE_INET_NTOA_R_2 1
-
-/* inet_ntoa_r() takes 3 args */
-#cmakedefine HAVE_INET_NTOA_R_3 1
-
/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
#cmakedefine HAVE_INET_NTOP 1
/* Define to 1 if you have a IPv6 capable working inet_pton function. */
#cmakedefine HAVE_INET_PTON 1
+/* Define to 1 if symbol `sa_family_t' exists */
+#cmakedefine HAVE_SA_FAMILY_T 1
+
+/* Define to 1 if symbol `ADDRESS_FAMILY' exists */
+#cmakedefine HAVE_ADDRESS_FAMILY 1
+
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
@@ -501,9 +483,6 @@
/* Define to 1 if you have the <pem.h> header file. */
#cmakedefine HAVE_PEM_H 1
-/* Define to 1 if you have the `perror' function. */
-#cmakedefine HAVE_PERROR 1
-
/* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE 1
@@ -645,15 +624,6 @@
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
-/* Define to 1 if you have the strlcat function. */
-#cmakedefine HAVE_STRLCAT 1
-
-/* Define to 1 if you have the `strlcpy' function. */
-#cmakedefine HAVE_STRLCPY 1
-
-/* Define to 1 if you have the strncasecmp function. */
-#cmakedefine HAVE_STRNCASECMP 1
-
/* Define to 1 if you have the strncmpi function. */
#cmakedefine HAVE_STRNCMPI 1
@@ -744,6 +714,9 @@
/* Define to 1 if you have the `utime' function. */
#cmakedefine HAVE_UTIME 1
+/* Define to 1 if you have the `utimes' function. */
+#cmakedefine HAVE_UTIMES 1
+
/* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H 1
@@ -871,9 +844,6 @@
/* Define to the function return type for recv. */
#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV}
-/* Define as the return type of signal handlers (`int' or `void'). */
-#cmakedefine RETSIGTYPE ${RETSIGTYPE}
-
/* Define to the type qualifier of arg 5 for select. */
#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5}
@@ -966,9 +936,6 @@ ${SIZEOF_TIME_T_CODE}
/* Define if you want to enable WIN32 threaded DNS lookup */
#cmakedefine USE_THREADS_WIN32 1
-/* Define to disable non-blocking sockets. */
-#cmakedefine USE_BLOCKING_SOCKETS 1
-
/* if GnuTLS is enabled */
#cmakedefine USE_GNUTLS 1
@@ -1089,3 +1056,9 @@ ${SIZEOF_TIME_T_CODE}
/* Define to 1 if you have the mach_absolute_time function. */
#cmakedefine HAVE_MACH_ABSOLUTE_TIME 1
+
+/* to enable Windows IDN */
+#cmakedefine USE_WIN32_IDN 1
+
+/* to make the compiler know the prototypes of Windows IDN APIs */
+#cmakedefine WANT_IDN_PROTOTYPES 1
diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c
index 2fc25bc17..b6f107e10 100644
--- a/Utilities/cmcurl/lib/curl_endian.c
+++ b/Utilities/cmcurl/lib/curl_endian.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -81,7 +81,7 @@ unsigned short Curl_read16_be(const unsigned char *buf)
((unsigned short)buf[1]));
}
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
+#if (SIZEOF_CURL_OFF_T > 4)
/*
* write32_le()
*
@@ -121,4 +121,4 @@ void Curl_write64_le(const __int64 value, unsigned char *buffer)
write32_le((int)value, buffer);
write32_le((int)(value >> 32), buffer + 4);
}
-#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
+#endif /* SIZEOF_CURL_OFF_T > 4 */
diff --git a/Utilities/cmcurl/lib/curl_endian.h b/Utilities/cmcurl/lib/curl_endian.h
index 341dfaf3c..4e12d7da4 100644
--- a/Utilities/cmcurl/lib/curl_endian.h
+++ b/Utilities/cmcurl/lib/curl_endian.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -31,7 +31,7 @@ unsigned int Curl_read32_le(const unsigned char *buf);
/* Converts a 16-bit integer from big endian */
unsigned short Curl_read16_be(const unsigned char *buf);
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
+#if (SIZEOF_CURL_OFF_T > 4)
/* Converts a 64-bit integer to little endian */
#if defined(HAVE_LONGLONG)
void Curl_write64_le(const long long value, unsigned char *buffer);
diff --git a/Utilities/cmcurl/lib/curl_get_line.c b/Utilities/cmcurl/lib/curl_get_line.c
index 438ede704..8f3b0bd8c 100644
--- a/Utilities/cmcurl/lib/curl_get_line.c
+++ b/Utilities/cmcurl/lib/curl_get_line.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -23,7 +23,7 @@
#include "curl_setup.h"
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
- defined(USE_HSTS)
+ !defined(CURL_DISABLE_HSTS)
#include "curl_get_line.h"
#include "curl_memory.h"
diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index 6445fbad0..acaaa1c68 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/lib/curl_gssapi.c
@@ -102,7 +102,7 @@ static size_t display_gss_error(OM_uint32 status, int type,
(char *)status_string.value);
}
gss_release_buffer(&min_stat, &status_string);
- } while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
+ } while(!GSS_ERROR(maj_stat) && msg_ctx);
return len;
}
diff --git a/Utilities/cmcurl/lib/curl_krb5.h b/Utilities/cmcurl/lib/curl_krb5.h
index 3f40f9a6c..ca0684074 100644
--- a/Utilities/cmcurl/lib/curl_krb5.h
+++ b/Utilities/cmcurl/lib/curl_krb5.h
@@ -29,7 +29,6 @@ struct Curl_sec_client_mech {
int (*auth)(void *, struct Curl_easy *data, struct connectdata *);
void (*end)(void *);
int (*check_prot)(void *, int);
- int (*overhead)(void *, int, int);
int (*encode)(void *, const void *, int, int, void **);
int (*decode)(void *, void *, int, int, struct connectdata *);
};
diff --git a/Utilities/cmcurl/lib/curl_multibyte.c b/Utilities/cmcurl/lib/curl_multibyte.c
index d327c8ba7..16418bee4 100644
--- a/Utilities/cmcurl/lib/curl_multibyte.c
+++ b/Utilities/cmcurl/lib/curl_multibyte.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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,7 +21,11 @@
***************************************************************************/
/*
- * This file is 'mem-include-scan' clean. See test 1132.
+ * This file is 'mem-include-scan' clean, which means memdebug.h and
+ * curl_memory.h are purposely not included in this file. See test 1132.
+ *
+ * The functions in this file are curlx functions which are not tracked by the
+ * curl memory tracker memdebug.
*/
#include "curl_setup.h"
@@ -82,6 +86,32 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
+int curlx_win32_open(const char *filename, int oflag, ...)
+{
+ int pmode = 0;
+
+#ifdef _UNICODE
+ int result = -1;
+ wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
+#endif
+
+ va_list param;
+ va_start(param, oflag);
+ if(oflag & O_CREAT)
+ pmode = va_arg(param, int);
+ va_end(param);
+
+#ifdef _UNICODE
+ if(filename_w)
+ result = _wopen(filename_w, oflag, pmode);
+ free(filename_w);
+ if(result != -1)
+ return result;
+#endif
+
+ return (_open)(filename, oflag, pmode);
+}
+
FILE *curlx_win32_fopen(const char *filename, const char *mode)
{
#ifdef _UNICODE
@@ -104,50 +134,38 @@ int curlx_win32_stat(const char *path, struct_stat *buffer)
int result = -1;
#ifdef _UNICODE
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
-#endif /* _UNICODE */
-
+ if(path_w) {
#if defined(USE_WIN32_SMALL_FILES)
-#if defined(_UNICODE)
- if(path_w)
result = _wstat(path_w, buffer);
- else
-#endif /* _UNICODE */
- result = _stat(path, buffer);
-#else /* USE_WIN32_SMALL_FILES */
-#if defined(_UNICODE)
- if(path_w)
+#else
result = _wstati64(path_w, buffer);
- else
+#endif
+ free(path_w);
+ if(result != -1)
+ return result;
+ }
#endif /* _UNICODE */
- result = _stati64(path, buffer);
-#endif /* USE_WIN32_SMALL_FILES */
-#ifdef _UNICODE
- free(path_w);
+#if defined(USE_WIN32_SMALL_FILES)
+ result = _stat(path, buffer);
+#else
+ result = _stati64(path, buffer);
#endif
-
return result;
}
int curlx_win32_access(const char *path, int mode)
{
- int result = -1;
-#ifdef _UNICODE
- wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
-#endif /* _UNICODE */
-
#if defined(_UNICODE)
- if(path_w)
- result = _waccess(path_w, mode);
- else
-#endif /* _UNICODE */
- result = _access(path, mode);
-
-#ifdef _UNICODE
+ wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
+ if(path_w) {
+ int result = _waccess(path_w, mode);
free(path_w);
-#endif
-
- return result;
+ if(result != -1)
+ return result;
+ }
+#endif /* _UNICODE */
+ return _access(path, mode);
}
#endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */
diff --git a/Utilities/cmcurl/lib/curl_multibyte.h b/Utilities/cmcurl/lib/curl_multibyte.h
index 8adaf4978..491155e6a 100644
--- a/Utilities/cmcurl/lib/curl_multibyte.h
+++ b/Utilities/cmcurl/lib/curl_multibyte.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -31,7 +31,6 @@
wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
-
#endif /* WIN32 */
/*
@@ -40,29 +39,23 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
* preprocessor conditional directives needed by code using these
* to differentiate UNICODE from non-UNICODE builds.
*
- * When building with UNICODE defined, these two macros
- * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
- * return a pointer to a newly allocated memory area holding result.
- * When the result is no longer needed, allocated memory is intended
- * to be free'ed with curlx_unicodefree().
+ * In the case of a non-UNICODE build the tchar strings are char strings that
+ * are duplicated via strdup and remain in whatever the passed in encoding is,
+ * which is assumed to be UTF-8 but may be other encoding. Therefore the
+ * significance of the conversion functions is primarily for UNICODE builds.
+ *
+ * Allocated memory should be free'd with curlx_unicodefree().
*
- * When building without UNICODE defined, this macros
- * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
- * return the pointer received as argument. curlx_unicodefree() does
- * no actual free'ing of this pointer it is simply set to NULL.
+ * Note: Because these are curlx functions their memory usage is not tracked
+ * by the curl memory tracker memdebug. You'll notice that curlx function-like
+ * macros call free and strdup in parentheses, eg (strdup)(ptr), and that's to
+ * ensure that the curl memdebug override macros do not replace them.
*/
#if defined(UNICODE) && defined(WIN32)
#define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
#define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
-#define curlx_unicodefree(ptr) \
- do { \
- if(ptr) { \
- (free)(ptr); \
- (ptr) = NULL; \
- } \
- } while(0)
typedef union {
unsigned short *tchar_ptr;
@@ -73,10 +66,8 @@ typedef union {
#else
-#define curlx_convert_UTF8_to_tchar(ptr) (ptr)
-#define curlx_convert_tchar_to_UTF8(ptr) (ptr)
-#define curlx_unicodefree(ptr) \
- do {(ptr) = NULL;} while(0)
+#define curlx_convert_UTF8_to_tchar(ptr) (strdup)(ptr)
+#define curlx_convert_tchar_to_UTF8(ptr) (strdup)(ptr)
typedef union {
char *tchar_ptr;
@@ -87,4 +78,12 @@ typedef union {
#endif /* UNICODE && WIN32 */
+#define curlx_unicodefree(ptr) \
+ do { \
+ if(ptr) { \
+ (free)(ptr); \
+ (ptr) = NULL; \
+ } \
+ } while(0)
+
#endif /* HEADER_CURL_MULTIBYTE_H */
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index 9a075ac90..89d4ec872 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -34,13 +34,12 @@
/* Please keep the SSL backend-specific #if branches in this order:
1. USE_OPENSSL
- 2. USE_GNUTLS_NETTLE
- 3. USE_GNUTLS
- 4. USE_NSS
- 5. USE_MBEDTLS
- 6. USE_SECTRANSP
- 7. USE_OS400CRYPTO
- 8. USE_WIN32_CRYPTO
+ 2. USE_GNUTLS
+ 3. USE_NSS
+ 4. USE_MBEDTLS
+ 5. USE_SECTRANSP
+ 6. USE_OS400CRYPTO
+ 7. USE_WIN32_CRYPTO
This ensures that:
- the same SSL branch gets activated throughout this source
@@ -74,13 +73,9 @@
# define DESKEY(x) &x
# endif
-#elif defined(USE_GNUTLS_NETTLE)
-
-# include <nettle/des.h>
-
#elif defined(USE_GNUTLS)
-# include <gcrypt.h>
+# include <nettle/des.h>
#elif defined(USE_NSS)
@@ -159,7 +154,7 @@ static void setup_des_key(const unsigned char *key_56,
DES_set_key(&key, ks);
}
-#elif defined(USE_GNUTLS_NETTLE)
+#elif defined(USE_GNUTLS)
static void setup_des_key(const unsigned char *key_56,
struct des_ctx *des)
@@ -176,26 +171,6 @@ static void setup_des_key(const unsigned char *key_56,
des_set_key(des, (const uint8_t *) key);
}
-#elif defined(USE_GNUTLS)
-
-/*
- * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
- */
-static void setup_des_key(const unsigned char *key_56,
- gcry_cipher_hd_t *des)
-{
- char key[8];
-
- /* Expand the 56-bit key to 64-bits */
- extend_key_56_to_64(key_56, key);
-
- /* Set the key parity to odd */
- Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
-
- /* Set the key */
- gcry_cipher_setkey(*des, key, sizeof(key));
-}
-
#elif defined(USE_NSS)
/*
@@ -402,7 +377,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
setup_des_key(keys + 14, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
DESKEY(ks), DES_ENCRYPT);
-#elif defined(USE_GNUTLS_NETTLE)
+#elif defined(USE_GNUTLS)
struct des_ctx des;
setup_des_key(keys, &des);
des_encrypt(&des, 8, results, plaintext);
@@ -410,23 +385,6 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
des_encrypt(&des, 8, results + 8, plaintext);
setup_des_key(keys + 14, &des);
des_encrypt(&des, 8, results + 16, plaintext);
-#elif defined(USE_GNUTLS)
- gcry_cipher_hd_t des;
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(keys, &des);
- gcry_cipher_encrypt(des, results, 8, plaintext, 8);
- gcry_cipher_close(des);
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(keys + 7, &des);
- gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
- gcry_cipher_close(des);
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(keys + 14, &des);
- gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
- gcry_cipher_close(des);
#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(plaintext, results, keys);
@@ -473,24 +431,12 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
setup_des_key(pw + 7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
DESKEY(ks), DES_ENCRYPT);
-#elif defined(USE_GNUTLS_NETTLE)
+#elif defined(USE_GNUTLS)
struct des_ctx des;
setup_des_key(pw, &des);
des_encrypt(&des, 8, lmbuffer, magic);
setup_des_key(pw + 7, &des);
des_encrypt(&des, 8, lmbuffer + 8, magic);
-#elif defined(USE_GNUTLS)
- gcry_cipher_hd_t des;
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(pw, &des);
- gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
- gcry_cipher_close(des);
-
- gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
- setup_des_key(pw + 7, &des);
- gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
- gcry_cipher_close(des);
#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(magic, lmbuffer, pw);
@@ -567,6 +513,56 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
+/* Timestamp in tenths of a microsecond since January 1, 1601 00:00:00 UTC. */
+struct ms_filetime {
+ unsigned int dwLowDateTime;
+ unsigned int dwHighDateTime;
+};
+
+/* Convert a time_t to an MS FILETIME (MS-DTYP section 2.3.3). */
+static void time2filetime(struct ms_filetime *ft, time_t t)
+{
+#if SIZEOF_TIME_T > 4
+ t = (t + CURL_OFF_T_C(11644473600)) * 10000000;
+ ft->dwLowDateTime = (unsigned int) (t & 0xFFFFFFFF);
+ ft->dwHighDateTime = (unsigned int) (t >> 32);
+#else
+ unsigned int r, s;
+ unsigned int i;
+
+ ft->dwLowDateTime = t & 0xFFFFFFFF;
+ ft->dwHighDateTime = 0;
+
+# ifndef HAVE_TIME_T_UNSIGNED
+ /* Extend sign if needed. */
+ if(ft->dwLowDateTime & 0x80000000)
+ ft->dwHighDateTime = ~0;
+# endif
+
+ /* Bias seconds to Jan 1, 1601.
+ 134774 days = 11644473600 seconds = 0x2B6109100 */
+ r = ft->dwLowDateTime;
+ ft->dwLowDateTime = (ft->dwLowDateTime + 0xB6109100U) & 0xFFFFFFFF;
+ ft->dwHighDateTime += ft->dwLowDateTime < r? 0x03: 0x02;
+
+ /* Convert to tenths of microseconds. */
+ ft->dwHighDateTime *= 10000000;
+ i = 32;
+ do {
+ i -= 8;
+ s = ((ft->dwLowDateTime >> i) & 0xFF) * (10000000 - 1);
+ r = (s << i) & 0xFFFFFFFF;
+ s >>= 1; /* Split shift to avoid width overflow. */
+ s >>= 31 - i;
+ ft->dwLowDateTime = (ft->dwLowDateTime + r) & 0xFFFFFFFF;
+ if(ft->dwLowDateTime < r)
+ s++;
+ ft->dwHighDateTime += s;
+ } while(i);
+ ft->dwHighDateTime &= 0xFFFFFFFF;
+#endif
+}
+
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
* (uppercase UserName + Domain) as the data
*/
@@ -640,22 +636,18 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
unsigned int len = 0;
unsigned char *ptr = NULL;
unsigned char hmac_output[HMAC_MD5_LENGTH];
- curl_off_t tw;
+ struct ms_filetime tw;
CURLcode result = CURLE_OK;
-#if CURL_SIZEOF_CURL_OFF_T < 8
-#error "this section needs 64bit support to work"
-#endif
-
/* Calculate the timestamp */
#ifdef DEBUGBUILD
char *force_timestamp = getenv("CURL_FORCETIME");
if(force_timestamp)
- tw = CURL_OFF_T_C(11644473600) * 10000000;
+ time2filetime(&tw, (time_t) 0);
else
#endif
- tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000;
+ time2filetime(&tw, time(NULL));
/* Calculate the response len */
len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN;
@@ -667,13 +659,14 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
/* Create the BLOB structure */
msnprintf((char *)ptr + HMAC_MD5_LENGTH, NTLMv2_BLOB_LEN,
- "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
- "%c%c%c%c", /* Reserved = 0 */
+ "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
+ "%c%c%c%c" /* Reserved = 0 */
+ "%c%c%c%c%c%c%c%c", /* Timestamp */
NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
- 0, 0, 0, 0);
+ 0, 0, 0, 0,
+ LONGQUARTET(tw.dwLowDateTime), LONGQUARTET(tw.dwHighDateTime));
- Curl_write64_le(tw, ptr + 24);
memcpy(ptr + 32, challenge_client, 8);
memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.h b/Utilities/cmcurl/lib/curl_ntlm_core.h
index fab628c59..02b39d485 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.h
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -30,7 +30,6 @@
then it must be initialized to be used by NTLM. */
#if !defined(USE_OPENSSL) && \
!defined(USE_WOLFSSL) && \
- !defined(USE_GNUTLS_NETTLE) && \
!defined(USE_GNUTLS) && \
defined(USE_NSS)
#define NTLM_NEEDS_NSS_INIT
@@ -48,19 +47,22 @@
#define USE_NTRESPONSES
/* Define USE_NTLM2SESSION in order to make the type-3 message include the
- NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and
- MD5 support */
-#if defined(USE_NTRESPONSES) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+ NTLM2Session response message, requires USE_NTRESPONSES defined to 1 */
+#if defined(USE_NTRESPONSES)
#define USE_NTLM2SESSION
#endif
/* Define USE_NTLM_V2 in order to allow the type-3 message to include the
- LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1
- and support for 64-bit integers. */
-#if defined(USE_NTRESPONSES) && (CURL_SIZEOF_CURL_OFF_T > 4)
+ LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 */
+#if defined(USE_NTRESPONSES)
#define USE_NTLM_V2
#endif
+/* Helpers to generate function byte arguments in little endian order */
+#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff))
+#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \
+ ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff))
+
void Curl_ntlm_core_lm_resp(const unsigned char *keys,
const unsigned char *plaintext,
unsigned char *results);
diff --git a/Utilities/cmcurl/lib/curl_path.c b/Utilities/cmcurl/lib/curl_path.c
index 6100d77bd..65106188c 100644
--- a/Utilities/cmcurl/lib/curl_path.c
+++ b/Utilities/cmcurl/lib/curl_path.c
@@ -48,7 +48,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
/* Check for /~/, indicating relative to the user's home directory */
if(data->conn->handler->protocol & CURLPROTO_SCP) {
real_path = malloc(working_path_len + 1);
- if(real_path == NULL) {
+ if(!real_path) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
@@ -62,7 +62,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
if((working_path_len > 1) && (working_path[1] == '~')) {
size_t homelen = strlen(homedir);
real_path = malloc(homelen + working_path_len + 1);
- if(real_path == NULL) {
+ if(!real_path) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
@@ -78,7 +78,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
}
else {
real_path = malloc(working_path_len + 1);
- if(real_path == NULL) {
+ if(!real_path) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
@@ -130,7 +130,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
/* Allocate enough space for home directory and filename + separator */
fullPathLength = strlen(cp) + strlen(homedir) + 2;
*path = malloc(fullPathLength);
- if(*path == NULL)
+ if(!*path)
return CURLE_OUT_OF_MEMORY;
/* Check for quoted filenames */
@@ -169,7 +169,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
else {
/* Read to end of filename - either to whitespace or terminator */
end = strpbrk(cp, WHITESPACE);
- if(end == NULL)
+ if(!end)
end = strchr(cp, '\0');
/* return pointer to second parameter if it exists */
*cpp = end + strspn(end, WHITESPACE);
diff --git a/Utilities/cmcurl/lib/curl_rtmp.c b/Utilities/cmcurl/lib/curl_rtmp.c
index fabdc8848..2fa026796 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.c
+++ b/Utilities/cmcurl/lib/curl_rtmp.c
@@ -79,6 +79,7 @@ const struct Curl_handler Curl_handler_rtmp = {
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_RTMP, /* defport */
CURLPROTO_RTMP, /* protocol */
CURLPROTO_RTMP, /* family */
@@ -101,6 +102,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPT, /* protocol */
CURLPROTO_RTMPT, /* family */
@@ -123,6 +125,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_RTMP, /* defport */
CURLPROTO_RTMPE, /* protocol */
CURLPROTO_RTMPE, /* family */
@@ -145,6 +148,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPTE, /* protocol */
CURLPROTO_RTMPTE, /* family */
@@ -167,6 +171,7 @@ const struct Curl_handler Curl_handler_rtmps = {
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPS, /* protocol */
CURLPROTO_RTMP, /* family */
@@ -189,6 +194,7 @@ const struct Curl_handler Curl_handler_rtmpts = {
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPTS, /* protocol */
CURLPROTO_RTMPT, /* family */
@@ -204,7 +210,7 @@ static CURLcode rtmp_setup_connection(struct Curl_easy *data,
RTMP_Init(r);
RTMP_SetBufferMS(r, DEF_BUFTIME);
- if(!RTMP_SetupURL(r, data->change.url)) {
+ if(!RTMP_SetupURL(r, data->state.url)) {
RTMP_Free(r);
return CURLE_URL_MALFORMAT;
}
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index ffeb75164..a4d1059cb 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -23,6 +23,8 @@
* RFC2831 DIGEST-MD5 authentication
* RFC4422 Simple Authentication and Security Layer (SASL)
* RFC4616 PLAIN authentication
+ * RFC5802 SCRAM-SHA-1 authentication
+ * RFC7677 SCRAM-SHA-256 authentication
* RFC6749 OAuth 2.0 Authorization Framework
* RFC7628 A Set of SASL Mechanisms for OAuth
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
@@ -56,7 +58,7 @@
static const struct {
const char *name; /* Name */
size_t len; /* Name length */
- unsigned int bit; /* Flag bit */
+ unsigned short bit; /* Flag bit */
} mechtable[] = {
{ "LOGIN", 5, SASL_MECH_LOGIN },
{ "PLAIN", 5, SASL_MECH_PLAIN },
@@ -67,6 +69,8 @@ static const struct {
{ "NTLM", 4, SASL_MECH_NTLM },
{ "XOAUTH2", 7, SASL_MECH_XOAUTH2 },
{ "OAUTHBEARER", 11, SASL_MECH_OAUTHBEARER },
+ { "SCRAM-SHA-1", 11, SASL_MECH_SCRAM_SHA_1 },
+ { "SCRAM-SHA-256",13, SASL_MECH_SCRAM_SHA_256 },
{ ZERO_NULL, 0, 0 }
};
@@ -90,6 +94,13 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
}
#endif
+#if defined(USE_GSASL)
+ /* Cleanup the GSASL structure */
+ if(authused & (SASL_MECH_SCRAM_SHA_1 | SASL_MECH_SCRAM_SHA_256)) {
+ Curl_auth_gsasl_cleanup(&conn->gsasl);
+ }
+#endif
+
#if defined(USE_NTLM)
/* Cleanup the NTLM structure */
if(authused == SASL_MECH_NTLM) {
@@ -117,7 +128,8 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
*
* Returns the SASL mechanism token or 0 if no match.
*/
-unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len)
+unsigned short Curl_sasl_decode_mech(const char *ptr, size_t maxlen,
+ size_t *len)
{
unsigned int i;
char c;
@@ -162,7 +174,7 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
if(!strncmp(value, "*", len))
sasl->prefmech = SASL_AUTH_DEFAULT;
else {
- unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
+ unsigned short mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
if(mechbit && mechlen == len)
sasl->prefmech |= mechbit;
else
@@ -215,6 +227,7 @@ static void state(struct SASL *sasl, struct Curl_easy *data,
"GSSAPI_NO_DATA",
"OAUTH2",
"OAUTH2_RESP",
+ "GSASL",
"CANCEL",
"FINAL",
/* LAST */
@@ -230,6 +243,49 @@ static void state(struct SASL *sasl, struct Curl_easy *data,
sasl->state = newstate;
}
+/* Get the SASL server message and convert it to binary. */
+static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
+ struct bufref *out)
+{
+ unsigned char *msg;
+ size_t msglen;
+ char *serverdata = NULL;
+ CURLcode result = CURLE_OK;
+
+ sasl->params->getmessage(data->state.buffer, &serverdata);
+ if(!serverdata)
+ result = CURLE_BAD_CONTENT_ENCODING;
+ else if(!*serverdata || *serverdata == '=')
+ Curl_bufref_set(out, NULL, 0, NULL);
+ else {
+ result = Curl_base64_decode(serverdata, &msg, &msglen);
+ if(!result)
+ Curl_bufref_set(out, msg, msglen, curl_free);
+ }
+ return result;
+}
+
+/* Encode the outgoing SASL message. */
+static CURLcode build_message(struct Curl_easy *data, struct bufref *msg)
+{
+ CURLcode result = CURLE_OK;
+ char *base64;
+ size_t base64len;
+
+ if(!Curl_bufref_ptr(msg)) /* Empty mesage. */
+ Curl_bufref_set(msg, "", 0, NULL);
+ else if(!Curl_bufref_len(msg)) /* Explicit empty response. */
+ Curl_bufref_set(msg, "=", 1, NULL);
+ else {
+ result = Curl_base64_encode(data, (const char *) Curl_bufref_ptr(msg),
+ Curl_bufref_len(msg), &base64, &base64len);
+ if(!result)
+ Curl_bufref_set(msg, base64, base64len, curl_free);
+ }
+
+ return result;
+}
+
/*
* Curl_sasl_can_authenticate()
*
@@ -260,25 +316,21 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
CURLcode result = CURLE_OK;
unsigned int enabledmechs;
const char *mech = NULL;
- char *resp = NULL;
- size_t len = 0;
+ struct bufref resp;
saslstate state1 = SASL_STOP;
saslstate state2 = SASL_FINAL;
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
-#else
- const char * const hostname = conn->host.name;
- const long int port = conn->remote_port;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
+ const long int port = SSL_HOST_PORT();
#if defined(USE_KERBEROS5) || defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
#endif
const char *oauth_bearer = data->set.str[STRING_BEARER];
+ struct bufref nullmsg;
+ Curl_bufref_init(&nullmsg);
+ Curl_bufref_init(&resp);
sasl->force_ir = force_ir; /* Latch for future use */
sasl->authused = 0; /* No mechanism used yet */
enabledmechs = sasl->authmechs & sasl->prefmech;
@@ -292,8 +344,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
sasl->authused = SASL_MECH_EXTERNAL;
if(force_ir || data->set.sasl_ir)
- result = Curl_auth_create_external_message(data, conn->user, &resp,
- &len);
+ result = Curl_auth_create_external_message(conn->user, &resp);
}
else if(conn->bits.user_passwd) {
#if defined(USE_KERBEROS5)
@@ -309,10 +360,39 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
result = Curl_auth_create_gssapi_user_message(data, conn->user,
conn->passwd,
service,
- data->conn->host.name,
+ conn->host.name,
sasl->mutual_auth,
NULL, &conn->krb5,
- &resp, &len);
+ &resp);
+ }
+ else
+#endif
+#ifdef USE_GSASL
+ if((enabledmechs & SASL_MECH_SCRAM_SHA_256) &&
+ Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_256,
+ &conn->gsasl)) {
+ mech = SASL_MECH_STRING_SCRAM_SHA_256;
+ sasl->authused = SASL_MECH_SCRAM_SHA_256;
+ state1 = SASL_GSASL;
+ state2 = SASL_GSASL;
+
+ result = Curl_auth_gsasl_start(data, conn->user,
+ conn->passwd, &conn->gsasl);
+ if(result == CURLE_OK && (force_ir || data->set.sasl_ir))
+ result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp);
+ }
+ else if((enabledmechs & SASL_MECH_SCRAM_SHA_1) &&
+ Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_1,
+ &conn->gsasl)) {
+ mech = SASL_MECH_STRING_SCRAM_SHA_1;
+ sasl->authused = SASL_MECH_SCRAM_SHA_1;
+ state1 = SASL_GSASL;
+ state2 = SASL_GSASL;
+
+ result = Curl_auth_gsasl_start(data, conn->user,
+ conn->passwd, &conn->gsasl);
+ if(result == CURLE_OK && (force_ir || data->set.sasl_ir))
+ result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp);
}
else
#endif
@@ -342,8 +422,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
conn->user, conn->passwd,
service,
hostname,
- &conn->ntlm, &resp,
- &len);
+ &conn->ntlm, &resp);
}
else
#endif
@@ -354,11 +433,11 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
sasl->authused = SASL_MECH_OAUTHBEARER;
if(force_ir || data->set.sasl_ir)
- result = Curl_auth_create_oauth_bearer_message(data, conn->user,
+ result = Curl_auth_create_oauth_bearer_message(conn->user,
hostname,
port,
oauth_bearer,
- &resp, &len);
+ &resp);
}
else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) {
mech = SASL_MECH_STRING_XOAUTH2;
@@ -366,9 +445,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
sasl->authused = SASL_MECH_XOAUTH2;
if(force_ir || data->set.sasl_ir)
- result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
+ result = Curl_auth_create_xoauth_bearer_message(conn->user,
oauth_bearer,
- &resp, &len);
+ &resp);
}
else if(enabledmechs & SASL_MECH_PLAIN) {
mech = SASL_MECH_STRING_PLAIN;
@@ -376,9 +455,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
sasl->authused = SASL_MECH_PLAIN;
if(force_ir || data->set.sasl_ir)
- result = Curl_auth_create_plain_message(data, conn->sasl_authzid,
+ result = Curl_auth_create_plain_message(conn->sasl_authzid,
conn->user, conn->passwd,
- &resp, &len);
+ &resp);
}
else if(enabledmechs & SASL_MECH_LOGIN) {
mech = SASL_MECH_STRING_LOGIN;
@@ -387,26 +466,29 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
sasl->authused = SASL_MECH_LOGIN;
if(force_ir || data->set.sasl_ir)
- result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
+ result = Curl_auth_create_login_message(conn->user, &resp);
}
}
if(!result && mech) {
- if(resp && sasl->params->maxirlen &&
- strlen(mech) + len > sasl->params->maxirlen) {
- free(resp);
- resp = NULL;
- }
+ if(Curl_bufref_ptr(&resp))
+ result = build_message(data, &resp);
+
+ if(sasl->params->maxirlen &&
+ strlen(mech) + Curl_bufref_len(&resp) > sasl->params->maxirlen)
+ Curl_bufref_free(&resp);
+
+ if(!result)
+ result = sasl->params->sendauth(data, conn, mech,
+ (const char *) Curl_bufref_ptr(&resp));
- result = sasl->params->sendauth(data, conn, mech, resp);
if(!result) {
*progress = SASL_INPROGRESS;
- state(sasl, data, resp ? state2 : state1);
+ state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1);
}
}
- free(resp);
-
+ Curl_bufref_free(&resp);
return result;
}
@@ -421,29 +503,20 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
saslstate newstate = SASL_FINAL;
- char *resp = NULL;
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
-#else
- const char * const hostname = conn->host.name;
- const long int port = conn->remote_port;
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
- char *chlg = NULL;
- size_t chlglen = 0;
-#endif
+ struct bufref resp;
+ const char * const hostname = SSL_HOST_NAME();
+ const long int port = SSL_HOST_PORT();
#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
- char *serverdata;
#endif
- size_t len = 0;
const char *oauth_bearer = data->set.str[STRING_BEARER];
+ struct bufref serverdata;
+ Curl_bufref_init(&serverdata);
+ Curl_bufref_init(&resp);
*progress = SASL_INPROGRESS;
if(sasl->state == SASL_FINAL) {
@@ -466,42 +539,45 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
*progress = SASL_DONE;
return result;
case SASL_PLAIN:
- result = Curl_auth_create_plain_message(data, conn->sasl_authzid,
- conn->user, conn->passwd,
- &resp, &len);
+ result = Curl_auth_create_plain_message(conn->sasl_authzid,
+ conn->user, conn->passwd, &resp);
break;
case SASL_LOGIN:
- result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
+ result = Curl_auth_create_login_message(conn->user, &resp);
newstate = SASL_LOGIN_PASSWD;
break;
case SASL_LOGIN_PASSWD:
- result = Curl_auth_create_login_message(data, conn->passwd, &resp, &len);
+ result = Curl_auth_create_login_message(conn->passwd, &resp);
break;
case SASL_EXTERNAL:
- result = Curl_auth_create_external_message(data, conn->user, &resp, &len);
+ result = Curl_auth_create_external_message(conn->user, &resp);
break;
-
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifdef USE_GSASL
+ case SASL_GSASL:
+ result = get_server_message(sasl, data, &serverdata);
+ if(!result)
+ result = Curl_auth_gsasl_token(data, &serverdata, &conn->gsasl, &resp);
+ if(!result && Curl_bufref_len(&resp) > 0)
+ newstate = SASL_GSASL;
+ break;
+#endif
case SASL_CRAMMD5:
- sasl->params->getmessage(data->state.buffer, &serverdata);
- result = Curl_auth_decode_cram_md5_message(serverdata, &chlg, &chlglen);
+ result = get_server_message(sasl, data, &serverdata);
if(!result)
- result = Curl_auth_create_cram_md5_message(data, chlg, conn->user,
- conn->passwd, &resp, &len);
- free(chlg);
+ result = Curl_auth_create_cram_md5_message(&serverdata, conn->user,
+ conn->passwd, &resp);
break;
case SASL_DIGESTMD5:
- sasl->params->getmessage(data->state.buffer, &serverdata);
- result = Curl_auth_create_digest_md5_message(data, serverdata,
- conn->user, conn->passwd,
- service,
- &resp, &len);
+ result = get_server_message(sasl, data, &serverdata);
+ if(!result)
+ result = Curl_auth_create_digest_md5_message(data, &serverdata,
+ conn->user, conn->passwd,
+ service, &resp);
newstate = SASL_DIGESTMD5_RESP;
break;
case SASL_DIGESTMD5_RESP:
- resp = strdup("");
- if(!resp)
- result = CURLE_OUT_OF_MEMORY;
+ /* Keep response NULL to output an empty line. */
break;
#endif
@@ -511,18 +587,19 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
result = Curl_auth_create_ntlm_type1_message(data,
conn->user, conn->passwd,
service, hostname,
- &conn->ntlm, &resp, &len);
+ &conn->ntlm, &resp);
newstate = SASL_NTLM_TYPE2MSG;
break;
case SASL_NTLM_TYPE2MSG:
/* Decode the type-2 message */
- sasl->params->getmessage(data->state.buffer, &serverdata);
- result = Curl_auth_decode_ntlm_type2_message(data, serverdata,
- &conn->ntlm);
+ result = get_server_message(sasl, data, &serverdata);
+ if(!result)
+ result = Curl_auth_decode_ntlm_type2_message(data, &serverdata,
+ &conn->ntlm);
if(!result)
result = Curl_auth_create_ntlm_type3_message(data, conn->user,
conn->passwd, &conn->ntlm,
- &resp, &len);
+ &resp);
break;
#endif
@@ -531,55 +608,59 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
result = Curl_auth_create_gssapi_user_message(data, conn->user,
conn->passwd,
service,
- data->conn->host.name,
+ conn->host.name,
sasl->mutual_auth, NULL,
&conn->krb5,
- &resp, &len);
+ &resp);
newstate = SASL_GSSAPI_TOKEN;
break;
case SASL_GSSAPI_TOKEN:
- sasl->params->getmessage(data->state.buffer, &serverdata);
- if(sasl->mutual_auth) {
- /* Decode the user token challenge and create the optional response
- message */
- result = Curl_auth_create_gssapi_user_message(data, NULL, NULL,
- NULL, NULL,
- sasl->mutual_auth,
- serverdata, &conn->krb5,
- &resp, &len);
- newstate = SASL_GSSAPI_NO_DATA;
+ result = get_server_message(sasl, data, &serverdata);
+ if(!result) {
+ if(sasl->mutual_auth) {
+ /* Decode the user token challenge and create the optional response
+ message */
+ result = Curl_auth_create_gssapi_user_message(data, NULL, NULL,
+ NULL, NULL,
+ sasl->mutual_auth,
+ &serverdata,
+ &conn->krb5,
+ &resp);
+ newstate = SASL_GSSAPI_NO_DATA;
+ }
+ else
+ /* Decode the security challenge and create the response message */
+ result = Curl_auth_create_gssapi_security_message(data, &serverdata,
+ &conn->krb5,
+ &resp);
}
- else
- /* Decode the security challenge and create the response message */
- result = Curl_auth_create_gssapi_security_message(data, serverdata,
- &conn->krb5,
- &resp, &len);
break;
case SASL_GSSAPI_NO_DATA:
- sasl->params->getmessage(data->state.buffer, &serverdata);
/* Decode the security challenge and create the response message */
- result = Curl_auth_create_gssapi_security_message(data, serverdata,
- &conn->krb5,
- &resp, &len);
+ result = get_server_message(sasl, data, &serverdata);
+ if(!result)
+ result = Curl_auth_create_gssapi_security_message(data, &serverdata,
+ &conn->krb5,
+ &resp);
break;
#endif
case SASL_OAUTH2:
/* Create the authorisation message */
if(sasl->authused == SASL_MECH_OAUTHBEARER) {
- result = Curl_auth_create_oauth_bearer_message(data, conn->user,
+ result = Curl_auth_create_oauth_bearer_message(conn->user,
hostname,
port,
oauth_bearer,
- &resp, &len);
+ &resp);
/* Failures maybe sent by the server as continuations for OAUTHBEARER */
newstate = SASL_OAUTH2_RESP;
}
else
- result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
+ result = Curl_auth_create_xoauth_bearer_message(conn->user,
oauth_bearer,
- &resp, &len);
+ &resp);
break;
case SASL_OAUTH2_RESP:
@@ -591,11 +672,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
return result;
}
else if(code == sasl->params->contcode) {
- /* Acknowledge the continuation by sending a 0x01 response base64
- encoded */
- resp = strdup("AQ==");
- if(!resp)
- result = CURLE_OUT_OF_MEMORY;
+ /* Acknowledge the continuation by sending a 0x01 response. */
+ Curl_bufref_set(&resp, "\x01", 1, NULL);
break;
}
else {
@@ -609,15 +687,15 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
sasl->authmechs ^= sasl->authused;
/* Start an alternative SASL authentication */
- result = Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress);
- newstate = sasl->state; /* Use state from Curl_sasl_start() */
- break;
+ return Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress);
default:
failf(data, "Unsupported SASL authentication mechanism");
result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */
break;
}
+ Curl_bufref_free(&serverdata);
+
switch(result) {
case CURLE_BAD_CONTENT_ENCODING:
/* Cancel dialog */
@@ -625,8 +703,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
newstate = SASL_CANCEL;
break;
case CURLE_OK:
- if(resp)
- result = sasl->params->sendcont(data, conn, resp);
+ result = build_message(data, &resp);
+ if(!result)
+ result = sasl->params->sendcont(data, conn,
+ (const char *) Curl_bufref_ptr(&resp));
break;
default:
newstate = SASL_STOP; /* Stop on error */
@@ -634,7 +714,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
break;
}
- free(resp);
+ Curl_bufref_free(&resp);
state(sasl, data, newstate);
diff --git a/Utilities/cmcurl/lib/curl_sasl.h b/Utilities/cmcurl/lib/curl_sasl.h
index 75a957583..e17d323eb 100644
--- a/Utilities/cmcurl/lib/curl_sasl.h
+++ b/Utilities/cmcurl/lib/curl_sasl.h
@@ -37,10 +37,12 @@ struct connectdata;
#define SASL_MECH_NTLM (1 << 6)
#define SASL_MECH_XOAUTH2 (1 << 7)
#define SASL_MECH_OAUTHBEARER (1 << 8)
+#define SASL_MECH_SCRAM_SHA_1 (1 << 9)
+#define SASL_MECH_SCRAM_SHA_256 (1 << 10)
/* Authentication mechanism values */
#define SASL_AUTH_NONE 0
-#define SASL_AUTH_ANY ~0U
+#define SASL_AUTH_ANY 0xffff
#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL)
/* Authentication mechanism strings */
@@ -53,6 +55,8 @@ struct connectdata;
#define SASL_MECH_STRING_NTLM "NTLM"
#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER"
+#define SASL_MECH_STRING_SCRAM_SHA_1 "SCRAM-SHA-1"
+#define SASL_MECH_STRING_SCRAM_SHA_256 "SCRAM-SHA-256"
/* SASL machine states */
typedef enum {
@@ -71,6 +75,7 @@ typedef enum {
SASL_GSSAPI_NO_DATA,
SASL_OAUTH2,
SASL_OAUTH2_RESP,
+ SASL_GSASL,
SASL_CANCEL,
SASL_FINAL
} saslstate;
@@ -103,9 +108,9 @@ struct SASLproto {
struct SASL {
const struct SASLproto *params; /* Protocol dependent parameters */
saslstate state; /* Current machine state */
- unsigned int authmechs; /* Accepted authentication mechanisms */
- unsigned int prefmech; /* Preferred authentication mechanism */
- unsigned int authused; /* Auth mechanism used for the connection */
+ unsigned short authmechs; /* Accepted authentication mechanisms */
+ unsigned short prefmech; /* Preferred authentication mechanism */
+ unsigned short authused; /* Auth mechanism used for the connection */
bool resetprefs; /* For URL auth option parsing. */
bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
bool force_ir; /* Protocol always supports initial response */
@@ -121,8 +126,8 @@ struct SASL {
void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused);
/* Convert a mechanism name to a token */
-unsigned int Curl_sasl_decode_mech(const char *ptr,
- size_t maxlen, size_t *len);
+unsigned short Curl_sasl_decode_mech(const char *ptr,
+ size_t maxlen, size_t *len);
/* Parse the URL login options */
CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index ef43b2b49..2d13a40a5 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -54,6 +54,16 @@
# ifndef NOGDI
# define NOGDI
# endif
+/* Detect Windows App environment which has a restricted access
+ * to the Win32 APIs. */
+# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
+ defined(WINAPI_FAMILY)
+# include <winapifamily.h>
+# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+# define CURL_WINDOWS_APP
+# endif
+# endif
#endif
/*
@@ -155,8 +165,6 @@
#include <curl/curl.h>
-#define CURL_SIZEOF_CURL_OFF_T SIZEOF_CURL_OFF_T
-
/*
* Disable other protocols when http is the only one desired.
*/
@@ -243,7 +251,11 @@
* performing this task will result in a synthesized IPv6 address.
*/
#if defined(__APPLE__) && !defined(USE_ARES)
+#include <TargetConditionals.h>
#define USE_RESOLVE_ON_IPS 1
+# if defined(TARGET_OS_OSX) && TARGET_OS_OSX
+# define CURL_OSX_CALL_COPYPROXIES 1
+# endif
#endif
#ifdef USE_LWIPSOCK
@@ -350,8 +362,10 @@
# define stat(fname,stp) curlx_win32_stat(fname, stp)
# define struct_stat struct _stati64
# define LSEEK_ERROR (__int64)-1
+# define open curlx_win32_open
# define fopen(fname,mode) curlx_win32_fopen(fname, mode)
# define access(fname,mode) curlx_win32_access(fname, mode)
+ int curlx_win32_open(const char *filename, int oflag, ...);
int curlx_win32_stat(const char *path, struct_stat *buffer);
FILE *curlx_win32_fopen(const char *filename, const char *mode);
int curlx_win32_access(const char *path, int mode);
@@ -371,9 +385,11 @@
# define fstat(fdes,stp) _fstat(fdes, stp)
# define stat(fname,stp) curlx_win32_stat(fname, stp)
# define struct_stat struct _stat
+# define open curlx_win32_open
# define fopen(fname,mode) curlx_win32_fopen(fname, mode)
# define access(fname,mode) curlx_win32_access(fname, mode)
int curlx_win32_stat(const char *path, struct_stat *buffer);
+ int curlx_win32_open(const char *filename, int oflag, ...);
FILE *curlx_win32_fopen(const char *filename, const char *mode);
int curlx_win32_access(const char *path, int mode);
# endif
@@ -423,7 +439,7 @@
#if (SIZEOF_CURL_OFF_T == 4)
# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
#else
- /* assume CURL_SIZEOF_CURL_OFF_T == 8 */
+ /* assume SIZEOF_CURL_OFF_T == 8 */
# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
#endif
#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
@@ -520,7 +536,6 @@
# undef HAVE_GETADDRINFO_THREADSAFE
# undef HAVE_FREEADDRINFO
# undef HAVE_GETADDRINFO
-# undef HAVE_GETNAMEINFO
# undef ENABLE_IPV6
# endif
#endif
@@ -627,7 +642,7 @@ int netware_init(void);
defined(USE_MBEDTLS) || \
defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \
defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK) || \
- defined(USE_BEARSSL)
+ defined(USE_BEARSSL) || defined(USE_RUSTLS)
#define USE_SSL /* SSL support has been enabled */
#endif
@@ -644,7 +659,7 @@ int netware_init(void);
#endif
/* Single point where USE_NTLM definition might be defined */
-#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+#ifndef CURL_DISABLE_CRYPTO_AUTH
#if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
@@ -718,13 +733,19 @@ int netware_init(void);
#endif
/*
- * Portable symbolic names for Winsock shutdown() mode flags.
+ * shutdown() flags for systems that don't define them
*/
-#ifdef USE_WINSOCK
-# define SHUT_RD 0x00
-# define SHUT_WR 0x01
-# define SHUT_RDWR 0x02
+#ifndef SHUT_RD
+#define SHUT_RD 0x00
+#endif
+
+#ifndef SHUT_WR
+#define SHUT_WR 0x01
+#endif
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 0x02
#endif
/* Define S_ISREG if not defined by system headers, f.e. MSVC */
@@ -775,20 +796,16 @@ endings either CRLF or LF so 't' is appropriate.
# endif
#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
-/* Detect Windows App environment which has a restricted access
- * to the Win32 APIs. */
-# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
- defined(WINAPI_FAMILY)
-# include <winapifamily.h>
-# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
- !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-# define CURL_WINDOWS_APP
-# endif
-# endif
-
-/* for systems that don't detect this in configure, use a sensible default */
+/* for systems that don't detect this in configure */
#ifndef CURL_SA_FAMILY_T
-#define CURL_SA_FAMILY_T unsigned short
+# if defined(HAVE_SA_FAMILY_T)
+# define CURL_SA_FAMILY_T sa_family_t
+# elif defined(HAVE_ADDRESS_FAMILY)
+# define CURL_SA_FAMILY_T ADDRESS_FAMILY
+# else
+/* use a sensible default */
+# define CURL_SA_FAMILY_T unsigned short
+# endif
#endif
/* Some convenience macros to get the larger/smaller value out of two given.
@@ -809,6 +826,10 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#define UNITTEST static
#endif
+#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+#define USE_HTTP2
+#endif
+
#if defined(USE_NGTCP2) || defined(USE_QUICHE)
#define ENABLE_QUIC
#endif
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index ef60bc7ae..22d0a063e 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -32,6 +32,7 @@
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
+#include <time.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
@@ -55,13 +56,6 @@
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#ifdef TIME_WITH_SYS_TIME
-#include <time.h>
-#endif
-#else
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
#endif
#ifdef WIN32
@@ -351,15 +345,6 @@ typedef int sig_atomic_t;
/*
- * Default return type for signal handlers.
- */
-
-#ifndef RETSIGTYPE
-#define RETSIGTYPE void
-#endif
-
-
-/*
* Macro used to include code only in debug builds.
*/
diff --git a/Utilities/cmcurl/lib/dict.c b/Utilities/cmcurl/lib/dict.c
index 4319dadba..625b05777 100644
--- a/Utilities/cmcurl/lib/dict.c
+++ b/Utilities/cmcurl/lib/dict.c
@@ -89,6 +89,7 @@ const struct Curl_handler Curl_handler_dict = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_DICT, /* defport */
CURLPROTO_DICT, /* protocol */
CURLPROTO_DICT, /* family */
@@ -214,14 +215,14 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
}
}
- if((word == NULL) || (*word == (char)0)) {
+ if(!word || (*word == (char)0)) {
infof(data, "lookup word is missing\n");
word = (char *)"default";
}
- if((database == NULL) || (*database == (char)0)) {
+ if(!database || (*database == (char)0)) {
database = (char *)"!";
}
- if((strategy == NULL) || (*strategy == (char)0)) {
+ if(!strategy || (*strategy == (char)0)) {
strategy = (char *)".";
}
@@ -265,11 +266,11 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
}
}
- if((word == NULL) || (*word == (char)0)) {
+ if(!word || (*word == (char)0)) {
infof(data, "lookup word is missing\n");
word = (char *)"default";
}
- if((database == NULL) || (*database == (char)0)) {
+ if(!database || (*database == (char)0)) {
database = (char *)"!";
}
diff --git a/Utilities/cmcurl/lib/doh.c b/Utilities/cmcurl/lib/doh.c
index 004244c8d..36f8cd58d 100644
--- a/Utilities/cmcurl/lib/doh.c
+++ b/Utilities/cmcurl/lib/doh.c
@@ -207,10 +207,12 @@ static int doh_done(struct Curl_easy *doh, CURLcode result)
}
#define ERROR_CHECK_SETOPT(x,y) \
-do { \
- result = curl_easy_setopt(doh, x, y); \
- if(result) \
- goto error; \
+do { \
+ result = curl_easy_setopt(doh, x, y); \
+ if(result && \
+ result != CURLE_NOT_BUILT_IN && \
+ result != CURLE_UNKNOWN_OPTION) \
+ goto error; \
} while(0)
static CURLcode dohprobe(struct Curl_easy *data,
@@ -282,84 +284,93 @@ static CURLcode dohprobe(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
#endif
ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
+ ERROR_CHECK_SETOPT(CURLOPT_SHARE, data->share);
+ if(data->set.err && data->set.err != stderr)
+ ERROR_CHECK_SETOPT(CURLOPT_STDERR, data->set.err);
if(data->set.verbose)
ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
if(data->set.no_signal)
ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L);
+ ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST,
+ data->set.doh_verifyhost ? 2L : 0L);
+ ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER,
+ data->set.doh_verifypeer ? 1L : 0L);
+ ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS,
+ data->set.doh_verifystatus ? 1L : 0L);
+
/* Inherit *some* SSL options from the user's transfer. This is a
- best-guess as to which options are needed for compatibility. #3661 */
+ best-guess as to which options are needed for compatibility. #3661
+
+ Note DOH does not inherit the user's proxy server so proxy SSL settings
+ have no effect and are not inherited. If that changes then two new
+ options should be added to check doh proxy insecure separately,
+ CURLOPT_DOH_PROXY_SSL_VERIFYHOST and CURLOPT_DOH_PROXY_SSL_VERIFYPEER.
+ */
if(data->set.ssl.falsestart)
ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L);
- if(data->set.ssl.primary.verifyhost)
- ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L);
-#ifndef CURL_DISABLE_PROXY
- if(data->set.proxy_ssl.primary.verifyhost)
- ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L);
- if(data->set.proxy_ssl.primary.verifypeer)
- ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
- if(data->set.str[STRING_SSL_CAFILE_PROXY]) {
- ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO,
- data->set.str[STRING_SSL_CAFILE_PROXY]);
- }
- if(data->set.str[STRING_SSL_CRLFILE_PROXY]) {
- ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE,
- data->set.str[STRING_SSL_CRLFILE_PROXY]);
- }
- if(data->set.proxy_ssl.no_revoke)
- ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
- else if(data->set.proxy_ssl.revoke_best_effort)
- ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS,
- CURLSSLOPT_REVOKE_BEST_EFFORT);
- if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
- ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
- data->set.str[STRING_SSL_CAPATH_PROXY]);
- }
-#endif
- if(data->set.ssl.primary.verifypeer)
- ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L);
- if(data->set.ssl.primary.verifystatus)
- ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L);
- if(data->set.str[STRING_SSL_CAFILE_ORIG]) {
+ if(data->set.str[STRING_SSL_CAFILE]) {
ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
- data->set.str[STRING_SSL_CAFILE_ORIG]);
+ data->set.str[STRING_SSL_CAFILE]);
+ }
+ if(data->set.blobs[BLOB_CAINFO]) {
+ ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB,
+ data->set.blobs[BLOB_CAINFO]);
}
- if(data->set.str[STRING_SSL_CAPATH_ORIG]) {
+ if(data->set.str[STRING_SSL_CAPATH]) {
ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
- data->set.str[STRING_SSL_CAPATH_ORIG]);
+ data->set.str[STRING_SSL_CAPATH]);
}
- if(data->set.str[STRING_SSL_CRLFILE_ORIG]) {
+ if(data->set.str[STRING_SSL_CRLFILE]) {
ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
- data->set.str[STRING_SSL_CRLFILE_ORIG]);
+ data->set.str[STRING_SSL_CRLFILE]);
}
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]);
+ 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]);
+ data->set.str[STRING_SSL_EGDSOCKET]);
}
- if(data->set.ssl.no_revoke)
- ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
- else if(data->set.ssl.revoke_best_effort)
- ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_REVOKE_BEST_EFFORT);
if(data->set.ssl.fsslctx)
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
if(data->set.ssl.fsslctxp)
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
if(data->set.str[STRING_SSL_EC_CURVES]) {
ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
- data->set.str[STRING_SSL_EC_CURVES]);
+ data->set.str[STRING_SSL_EC_CURVES]);
+ }
+
+ {
+ long mask =
+ (data->set.ssl.enable_beast ?
+ CURLSSLOPT_ALLOW_BEAST : 0) |
+ (data->set.ssl.no_revoke ?
+ CURLSSLOPT_NO_REVOKE : 0) |
+ (data->set.ssl.no_partialchain ?
+ CURLSSLOPT_NO_PARTIALCHAIN : 0) |
+ (data->set.ssl.revoke_best_effort ?
+ CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
+ (data->set.ssl.native_ca_store ?
+ CURLSSLOPT_NATIVE_CA : 0) |
+ (data->set.ssl.auto_client_cert ?
+ CURLSSLOPT_AUTO_CLIENT_CERT : 0);
+
+ curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask);
}
doh->set.fmultidone = doh_done;
doh->set.dohfor = data; /* identify for which transfer this is done */
p->easy = doh;
- /* add this transfer to the multi handle */
+ /* DOH private_data must be null because the user must have a way to
+ distinguish their transfer's handle from DOH handles in user
+ callbacks (ie SSL CTX callback). */
+ DEBUGASSERT(!data->set.private_data);
+
if(curl_multi_add_handle(multi, doh))
goto error;
}
@@ -409,17 +420,15 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
if(!dohp->headers)
goto error;
- if(conn->ip_version != CURL_IPRESOLVE_V6) {
- /* create IPv4 DOH request */
- result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4],
- DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
- data->multi, dohp->headers);
- if(result)
- goto error;
- dohp->pending++;
- }
+ /* create IPv4 DOH request */
+ result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4],
+ DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
+ data->multi, dohp->headers);
+ if(result)
+ goto error;
+ dohp->pending++;
- if(conn->ip_version != CURL_IPRESOLVE_V4) {
+ if(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],
diff --git a/Utilities/cmcurl/lib/dynbuf.h b/Utilities/cmcurl/lib/dynbuf.h
index 484e40c64..252411f84 100644
--- a/Utilities/cmcurl/lib/dynbuf.h
+++ b/Utilities/cmcurl/lib/dynbuf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2020, 2021, 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
@@ -74,7 +74,7 @@ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
#define DYN_DOH_CNAME 256
#define DYN_PAUSE_BUFFER (64 * 1024 * 1024)
#define DYN_HAXPROXY 2048
-#define DYN_HTTP_REQUEST (128*1024)
+#define DYN_HTTP_REQUEST (1024*1024)
#define DYN_H2_HEADERS (128*1024)
#define DYN_H2_TRAILERS (128*1024)
#define DYN_APRINTF 8000000
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index 0fb255af4..530b7c73f 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -789,7 +789,6 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
/* duplicate all blobs */
for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]);
- /* Curl_setstropt return CURLE_BAD_FUNCTION_ARGUMENT with blob */
if(result)
return result;
}
@@ -810,7 +809,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
if(src->set.resolve)
- dst->change.resolve = dst->set.resolve;
+ dst->state.resolve = dst->set.resolve;
return result;
}
@@ -858,25 +857,25 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
}
/* duplicate all values in 'change' */
- if(data->change.cookielist) {
- outcurl->change.cookielist =
- Curl_slist_duplicate(data->change.cookielist);
- if(!outcurl->change.cookielist)
+ if(data->state.cookielist) {
+ outcurl->state.cookielist =
+ Curl_slist_duplicate(data->state.cookielist);
+ if(!outcurl->state.cookielist)
goto fail;
}
- if(data->change.url) {
- outcurl->change.url = strdup(data->change.url);
- if(!outcurl->change.url)
+ if(data->state.url) {
+ outcurl->state.url = strdup(data->state.url);
+ if(!outcurl->state.url)
goto fail;
- outcurl->change.url_alloc = TRUE;
+ outcurl->state.url_alloc = TRUE;
}
- if(data->change.referer) {
- outcurl->change.referer = strdup(data->change.referer);
- if(!outcurl->change.referer)
+ if(data->state.referer) {
+ outcurl->state.referer = strdup(data->state.referer);
+ if(!outcurl->state.referer)
goto fail;
- outcurl->change.referer_alloc = TRUE;
+ outcurl->state.referer_alloc = TRUE;
}
/* Reinitialize an SSL engine for the new handle
@@ -895,7 +894,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
(void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]);
}
#endif
-#ifdef USE_HSTS
+#ifndef CURL_DISABLE_HSTS
if(data->hsts) {
outcurl->hsts = Curl_hsts_init();
if(!outcurl->hsts)
@@ -947,12 +946,12 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
fail:
if(outcurl) {
- curl_slist_free_all(outcurl->change.cookielist);
- outcurl->change.cookielist = NULL;
+ curl_slist_free_all(outcurl->state.cookielist);
+ outcurl->state.cookielist = NULL;
Curl_safefree(outcurl->state.buffer);
Curl_dyn_free(&outcurl->state.headerb);
- Curl_safefree(outcurl->change.url);
- Curl_safefree(outcurl->change.referer);
+ Curl_safefree(outcurl->state.url);
+ Curl_safefree(outcurl->state.referer);
Curl_altsvc_cleanup(&outcurl->asi);
Curl_hsts_cleanup(&outcurl->hsts);
Curl_freeset(outcurl);
@@ -1034,8 +1033,8 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
/* Unpause parts in active mime tree. */
if((k->keepon & ~newstate & KEEP_SEND_PAUSE) &&
- (data->mstate == CURLM_STATE_PERFORM ||
- data->mstate == CURLM_STATE_TOOFAST) &&
+ (data->mstate == MSTATE_PERFORMING ||
+ data->mstate == MSTATE_RATELIMITING) &&
data->state.fread_func == (curl_read_callback) Curl_mime_read) {
Curl_mime_unpause(data->state.in);
}
@@ -1052,8 +1051,6 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
unsigned int i;
unsigned int count = data->state.tempcount;
struct tempbuf writebuf[3]; /* there can only be three */
- struct connectdata *conn = data->conn;
- struct Curl_easy *saved_data = NULL;
/* copy the structs to allow for immediate re-pausing */
for(i = 0; i < data->state.tempcount; i++) {
@@ -1062,12 +1059,6 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
}
data->state.tempcount = 0;
- /* set the connection's current owner */
- if(conn->data != data) {
- saved_data = conn->data;
- conn->data = data;
- }
-
for(i = 0; i < count; i++) {
/* even if one function returns error, this loops through and frees
all buffers */
@@ -1078,10 +1069,6 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
Curl_dyn_free(&writebuf[i].b);
}
- /* recover previous owner of the connection */
- if(saved_data)
- conn->data = saved_data;
-
if(result)
return result;
}
@@ -1117,7 +1104,7 @@ static CURLcode easy_connection(struct Curl_easy *data,
curl_socket_t *sfd,
struct connectdata **connp)
{
- if(data == NULL)
+ if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
/* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
@@ -1183,6 +1170,7 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
CURLcode result;
ssize_t n1;
struct connectdata *c = NULL;
+ SIGPIPE_VARIABLE(pipe_st);
if(Curl_is_in_callback(data))
return CURLE_RECURSIVE_API_CALL;
@@ -1197,7 +1185,9 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
Curl_attach_connnection(data, c);
*n = 0;
+ sigpipe_ignore(data, &pipe_st);
result = Curl_write(data, sfd, buffer, buflen, &n1);
+ sigpipe_restore(&pipe_st);
if(n1 == -1)
return CURLE_SEND_ERROR;
diff --git a/Utilities/cmcurl/lib/easyoptions.c b/Utilities/cmcurl/lib/easyoptions.c
index b54829ba3..4e65e3525 100644
--- a/Utilities/cmcurl/lib/easyoptions.c
+++ b/Utilities/cmcurl/lib/easyoptions.c
@@ -38,6 +38,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0},
{"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0},
{"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0},
+ {"CAINFO_BLOB", CURLOPT_CAINFO_BLOB, CURLOT_BLOB, 0},
{"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0},
{"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0},
{"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0},
@@ -78,6 +79,9 @@ struct curl_easyoption Curl_easyopts[] = {
{"DNS_SERVERS", CURLOPT_DNS_SERVERS, CURLOT_STRING, 0},
{"DNS_SHUFFLE_ADDRESSES", CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOT_LONG, 0},
{"DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOT_LONG, 0},
+ {"DOH_SSL_VERIFYHOST", CURLOPT_DOH_SSL_VERIFYHOST, CURLOT_LONG, 0},
+ {"DOH_SSL_VERIFYPEER", CURLOPT_DOH_SSL_VERIFYPEER, CURLOT_LONG, 0},
+ {"DOH_SSL_VERIFYSTATUS", CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOT_LONG, 0},
{"DOH_URL", CURLOPT_DOH_URL, CURLOT_STRING, 0},
{"EGDSOCKET", CURLOPT_EGDSOCKET, CURLOT_STRING, 0},
{"ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, CURLOT_FLAG_ALIAS},
@@ -202,6 +206,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"PROXYUSERNAME", CURLOPT_PROXYUSERNAME, CURLOT_STRING, 0},
{"PROXYUSERPWD", CURLOPT_PROXYUSERPWD, CURLOT_STRING, 0},
{"PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 0},
+ {"PROXY_CAINFO_BLOB", CURLOPT_PROXY_CAINFO_BLOB, CURLOT_BLOB, 0},
{"PROXY_CAPATH", CURLOPT_PROXY_CAPATH, CURLOT_STRING, 0},
{"PROXY_CRLFILE", CURLOPT_PROXY_CRLFILE, CURLOT_STRING, 0},
{"PROXY_ISSUERCERT", CURLOPT_PROXY_ISSUERCERT, CURLOT_STRING, 0},
@@ -349,6 +354,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
- return ((CURLOPT_LASTENTRY%10000) != (305 + 1));
+ return ((CURLOPT_LASTENTRY%10000) != (310 + 1));
}
#endif
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index dd8a1fd12..0420db345 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -111,6 +111,7 @@ const struct Curl_handler Curl_handler_file = {
file_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
0, /* defport */
CURLPROTO_FILE, /* protocol */
CURLPROTO_FILE, /* family */
@@ -410,19 +411,21 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
struct tm buffer;
const struct tm *tm = &buffer;
char header[80];
+ int headerlen;
+ char accept_ranges[24]= { "Accept-ranges: bytes\r\n" };
if(expected_size >= 0) {
- msnprintf(header, sizeof(header),
+ headerlen = msnprintf(header, sizeof(header),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
expected_size);
- result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen);
if(result)
return result;
- }
- result = Curl_client_write(data, CLIENTWRITE_HEADER,
- (char *)"Accept-ranges: bytes\r\n", 0);
- if(result)
- return result;
+ result = Curl_client_write(data, CLIENTWRITE_HEADER,
+ accept_ranges, strlen(accept_ranges));
+ if(result != CURLE_OK)
+ return result;
+ }
filetime = (time_t)statbuf.st_mtime;
result = Curl_gmtime(filetime, &buffer);
@@ -430,7 +433,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
return result;
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
- msnprintf(header, sizeof(header),
+ headerlen = msnprintf(header, sizeof(header),
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
@@ -440,7 +443,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
tm->tm_min,
tm->tm_sec,
data->set.opt_no_body ? "": "\r\n");
- result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen);
if(result)
return result;
/* set the file size to make it available post transfer */
@@ -464,18 +467,23 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
data->state.resume_from += (curl_off_t)statbuf.st_size;
}
- if(data->state.resume_from <= expected_size)
- expected_size -= data->state.resume_from;
- else {
- failf(data, "failed to resume file:// transfer");
- return CURLE_BAD_DOWNLOAD_RESUME;
+ if(data->state.resume_from > 0) {
+ /* We check explicitly if we have a start offset, because
+ * expected_size may be -1 if we don't know how large the file is,
+ * in which case we should not adjust it. */
+ if(data->state.resume_from <= expected_size)
+ expected_size -= data->state.resume_from;
+ else {
+ failf(data, "failed to resume file:// transfer");
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
}
/* A high water mark has been specified so we obey... */
if(data->req.maxdownload > 0)
expected_size = data->req.maxdownload;
- if(!fstated || (expected_size == 0))
+ if(!fstated || (expected_size <= 0))
size_known = FALSE;
else
size_known = TRUE;
@@ -484,7 +492,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
this is both more efficient than the former call to download() and
it avoids problems with select() and recv() on file descriptors
in Winsock */
- if(fstated)
+ if(size_known)
Curl_pgrsSetDownloadSize(data, expected_size);
if(data->state.resume_from) {
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index f8f970cc8..425b0afec 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -175,6 +175,7 @@ const struct Curl_handler Curl_handler_ftp = {
ftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_FTP, /* defport */
CURLPROTO_FTP, /* protocol */
CURLPROTO_FTP, /* family */
@@ -205,6 +206,7 @@ const struct Curl_handler Curl_handler_ftps = {
ftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_FTPS, /* defport */
CURLPROTO_FTPS, /* protocol */
CURLPROTO_FTP, /* family */
@@ -1090,7 +1092,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
else
res = NULL; /* failure! */
- if(res == NULL) {
+ if(!res) {
failf(data, "failed to resolve the address provided to PORT: %s", host);
free(addr);
return CURLE_FTP_PORT_FAILED;
@@ -1357,7 +1359,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
struct FTP *ftp = data->req.p.ftp;
struct connectdata *conn = data->conn;
- if(ftp->transfer != FTPTRANSFER_BODY) {
+ if(ftp->transfer != PPTRANSFER_BODY) {
/* doesn't transfer any data */
/* still possibly do PRE QUOTE jobs */
@@ -1378,7 +1380,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
data->set.str[STRING_CUSTOMREQUEST]?
data->set.str[STRING_CUSTOMREQUEST]:
- (data->set.ftp_list_only?"NLST":"LIST"));
+ (data->state.list_only?"NLST":"LIST"));
else if(data->set.upload)
result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
conn->proto.ftpc.file);
@@ -1401,7 +1403,7 @@ static CURLcode ftp_state_rest(struct Curl_easy *data,
struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
+ if((ftp->transfer != PPTRANSFER_BODY) && ftpc->file) {
/* if a "head"-like request is being made (on a file) */
/* Determine if server can respond to REST command and therefore
@@ -1423,7 +1425,7 @@ static CURLcode ftp_state_size(struct Curl_easy *data,
struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
+ if((ftp->transfer == PPTRANSFER_INFO) && ftpc->file) {
/* if a "head"-like request is being made (on a file) */
/* we know ftpc->file is a valid pointer to a file name */
@@ -1485,7 +1487,7 @@ static CURLcode ftp_state_list(struct Curl_easy *data)
cmd = aprintf("%s%s%s",
data->set.str[STRING_CUSTOMREQUEST]?
data->set.str[STRING_CUSTOMREQUEST]:
- (data->set.ftp_list_only?"NLST":"LIST"),
+ (data->state.list_only?"NLST":"LIST"),
lstArg? " ": "",
lstArg? lstArg: "");
free(lstArg);
@@ -1525,17 +1527,17 @@ static CURLcode ftp_state_type(struct Curl_easy *data)
information. Which in FTP can't be much more than the file size and
date. */
if(data->set.opt_no_body && ftpc->file &&
- ftp_need_type(conn, data->set.prefer_ascii)) {
+ ftp_need_type(conn, data->state.prefer_ascii)) {
/* The SIZE command is _not_ RFC 959 specified, and therefore many servers
may not support it! It is however the only way we have to get a file's
size! */
- ftp->transfer = FTPTRANSFER_INFO;
+ ftp->transfer = PPTRANSFER_INFO;
/* this means no actual transfer will be made */
/* Some servers return different sizes for different modes, and thus we
must set the proper type before we check the size */
- result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_TYPE);
+ result = ftp_nb_type(data, conn, data->state.prefer_ascii, FTP_TYPE);
if(result)
return result;
}
@@ -1578,6 +1580,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
struct connectdata *conn = data->conn;
struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
+ bool append = data->set.remote_append;
if((data->state.resume_from && !sizechecked) ||
((data->state.resume_from > 0) && sizechecked)) {
@@ -1604,7 +1607,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
}
/* enable append */
- data->set.ftp_append = TRUE;
+ append = TRUE;
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
@@ -1652,7 +1655,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
/* Set ->transfer so that we won't get any error in
* ftp_done() because we didn't transfer anything! */
- ftp->transfer = FTPTRANSFER_NONE;
+ ftp->transfer = PPTRANSFER_NONE;
state(data, FTP_STOP);
return CURLE_OK;
@@ -1661,8 +1664,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
/* we've passed, proceed as normal */
} /* resume_from */
- result = Curl_pp_sendf(data, &ftpc->pp,
- data->set.ftp_append?"APPE %s":"STOR %s",
+ result = Curl_pp_sendf(data, &ftpc->pp, append?"APPE %s":"STOR %s",
ftpc->file);
if(!result)
state(data, FTP_STOR);
@@ -1739,7 +1741,7 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
result = ftp_state_cwd(data, conn);
break;
case FTP_RETR_PREQUOTE:
- if(ftp->transfer != FTPTRANSFER_BODY)
+ if(ftp->transfer != PPTRANSFER_BODY)
state(data, FTP_STOP);
else {
if(ftpc->known_filesize != -1) {
@@ -1747,13 +1749,19 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
result = ftp_state_retr(data, ftpc->known_filesize);
}
else {
- if(data->set.ignorecl) {
- /* This code is to support download of growing files. It prevents
- the state machine from requesting the file size from the
- server. With an unknown file size the download continues until
- the server terminates it, otherwise the client stops if the
- received byte count exceeds the reported file size. Set option
- CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/
+ if(data->set.ignorecl || data->state.prefer_ascii) {
+ /* 'ignorecl' is used to support download of growing files. It
+ prevents the state machine from requesting the file size from
+ the server. With an unknown file size the download continues
+ until the server terminates it, otherwise the client stops if
+ the received byte count exceeds the reported file size. Set
+ option CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this
+ behavior.
+
+ In addition: asking for the size for 'TYPE A' transfers is not
+ constructive since servers don't report the converted size. So
+ skip it.
+ */
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
if(!result)
state(data, FTP_RETR);
@@ -2092,6 +2100,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
data->set.get_filetime &&
(data->info.filetime >= 0) ) {
char headerbuf[128];
+ int headerbuflen;
time_t filetime = data->info.filetime;
struct tm buffer;
const struct tm *tm = &buffer;
@@ -2101,7 +2110,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
return result;
/* format: "Tue, 15 Nov 1994 12:45:26" */
- msnprintf(headerbuf, sizeof(headerbuf),
+ headerbuflen = msnprintf(headerbuf, sizeof(headerbuf),
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
@@ -2110,7 +2119,8 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
- result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf, 0);
+ result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf,
+ headerbuflen);
if(result)
return result;
} /* end of a ridiculous amount of conditionals */
@@ -2133,7 +2143,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
default:
if(data->info.filetime <= data->set.timevalue) {
infof(data, "The requested document is not new enough\n");
- ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
+ ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
state(data, FTP_STOP);
return CURLE_OK;
@@ -2142,7 +2152,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
case CURL_TIMECOND_IFUNMODSINCE:
if(data->info.filetime > data->set.timevalue) {
infof(data, "The requested document is not old enough\n");
- ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
+ ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
state(data, FTP_STOP);
return CURLE_OK;
@@ -2250,7 +2260,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
/* Set ->transfer so that we won't get any error in ftp_done()
* because we didn't transfer the any file */
- ftp->transfer = FTPTRANSFER_NONE;
+ ftp->transfer = PPTRANSFER_NONE;
state(data, FTP_STOP);
return CURLE_OK;
}
@@ -2303,17 +2313,21 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
}
else if(ftpcode == 550) { /* "No such file or directory" */
- failf(data, "The file does not exist");
- return CURLE_REMOTE_FILE_NOT_FOUND;
+ /* allow a SIZE failure for (resumed) uploads, when probing what command
+ to use */
+ if(instate != FTP_STOR_SIZE) {
+ failf(data, "The file does not exist");
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+ }
}
if(instate == FTP_SIZE) {
#ifdef CURL_FTP_HTTPSTYLE_HEAD
if(-1 != filesize) {
char clbuf[128];
- msnprintf(clbuf, sizeof(clbuf),
+ int clbuflen = msnprintf(clbuf, sizeof(clbuf),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
- result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, 0);
+ result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, clbuflen);
if(result)
return result;
}
@@ -2347,7 +2361,8 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
#ifdef CURL_FTP_HTTPSTYLE_HEAD
if(ftpcode == 350) {
char buffer[24]= { "Accept-ranges: bytes\r\n" };
- result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer, 0);
+ result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer,
+ strlen(buffer));
if(result)
return result;
}
@@ -2448,7 +2463,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
*/
if((instate != FTP_LIST) &&
- !data->set.prefer_ascii &&
+ !data->state.prefer_ascii &&
(ftp->downloadsize < 1)) {
/*
* It seems directory listings either don't show the size or very
@@ -2476,7 +2491,8 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
bytes--;
}
/* if we have nothing but digits: */
- if(bytes++) {
+ if(bytes) {
+ ++bytes;
/* get the number! */
(void)curlx_strtoofft(bytes, NULL, 0, &size);
}
@@ -2487,7 +2503,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
if(size > data->req.maxdownload && data->req.maxdownload > 0)
size = data->req.size = data->req.maxdownload;
- else if((instate != FTP_LIST) && (data->set.prefer_ascii))
+ else if((instate != FTP_LIST) && (data->state.prefer_ascii))
size = -1; /* kludge for servers that understate ASCII mode file size */
infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n",
@@ -2521,7 +2537,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
else {
if((instate == FTP_LIST) && (ftpcode == 450)) {
/* simply no matching files in the dir listing */
- ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */
+ ftp->transfer = PPTRANSFER_NONE; /* don't download anything */
state(data, FTP_STOP); /* this phase is over */
}
else {
@@ -3291,7 +3307,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
close_secondarysocket(data, conn);
}
- if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
+ if(!result && (ftp->transfer == PPTRANSFER_BODY) && ftpc->ctl_valid &&
pp->pending_resp && !premature) {
/*
* Let's see what the server says about the transfer we just performed,
@@ -3314,8 +3330,10 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */
}
- if(result)
+ if(result) {
+ Curl_safefree(ftp->pathalloc);
return result;
+ }
if(ftpc->dont_check && data->req.maxdownload > 0) {
/* we have just sent ABOR and there is no reliable way to check if it was
@@ -3351,7 +3369,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
if((-1 != data->state.infilesize) &&
(data->state.infilesize != data->req.writebytecount) &&
!data->set.crlf &&
- (ftp->transfer == FTPTRANSFER_BODY)) {
+ (ftp->transfer == PPTRANSFER_BODY)) {
failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
" out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
data->req.bytecount, data->state.infilesize);
@@ -3383,7 +3401,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
}
/* clear these for next connection */
- ftp->transfer = FTPTRANSFER_BODY;
+ ftp->transfer = PPTRANSFER_BODY;
ftpc->dont_check = FALSE;
/* Send any post-transfer QUOTE strings? */
@@ -3594,7 +3612,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
*completep = 0;
}
- if(ftp->transfer <= FTPTRANSFER_INFO) {
+ if(ftp->transfer <= PPTRANSFER_INFO) {
/* a transfer is about to take place, or if not a file name was given
so we'll do a SIZE on it later and then we need the right TYPE first */
@@ -3620,7 +3638,8 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
}
}
else if(data->set.upload) {
- result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_STOR_TYPE);
+ result = ftp_nb_type(data, conn, data->state.prefer_ascii,
+ FTP_STOR_TYPE);
if(result)
return result;
@@ -3641,13 +3660,13 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
if(result)
;
- else if(data->set.ftp_list_only || !ftpc->file) {
+ else if(data->state.list_only || !ftpc->file) {
/* The specified path ends with a slash, and therefore we think this
is a directory that is requested, use LIST. But before that we
need to set ASCII transfer mode. */
/* But only if a body transfer was requested. */
- if(ftp->transfer == FTPTRANSFER_BODY) {
+ if(ftp->transfer == PPTRANSFER_BODY) {
result = ftp_nb_type(data, conn, TRUE, FTP_LIST_TYPE);
if(result)
return result;
@@ -3655,7 +3674,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
/* otherwise just fall through */
}
else {
- result = ftp_nb_type(data, conn, data->set.prefer_ascii,
+ result = ftp_nb_type(data, conn, data->state.prefer_ascii,
FTP_RETR_TYPE);
if(result)
return result;
@@ -3703,7 +3722,7 @@ CURLcode ftp_perform(struct Curl_easy *data,
if(data->set.opt_no_body) {
/* requested no body means no transfer... */
struct FTP *ftp = data->req.p.ftp;
- ftp->transfer = FTPTRANSFER_INFO;
+ ftp->transfer = PPTRANSFER_INFO;
}
*dophase_done = FALSE; /* not done yet */
@@ -4194,7 +4213,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
ftpc->file = NULL; /* instead of point to a zero byte,
we make it a NULL pointer */
- if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) {
+ if(data->set.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) {
/* We need a file name when uploading. Return error! */
failf(data, "Uploading to a URL without a file name!");
free(rawPath);
@@ -4242,7 +4261,7 @@ static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
}
}
- if(ftp->transfer != FTPTRANSFER_BODY)
+ if(ftp->transfer != PPTRANSFER_BODY)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
else if(!connected)
@@ -4346,23 +4365,23 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
switch(command) {
case 'A': /* ASCII mode */
- data->set.prefer_ascii = TRUE;
+ data->state.prefer_ascii = TRUE;
break;
case 'D': /* directory mode */
- data->set.ftp_list_only = TRUE;
+ data->state.list_only = TRUE;
break;
case 'I': /* binary mode */
default:
/* switch off ASCII */
- data->set.prefer_ascii = FALSE;
+ data->state.prefer_ascii = FALSE;
break;
}
}
/* get some initial data into the ftp struct */
- ftp->transfer = FTPTRANSFER_BODY;
+ ftp->transfer = PPTRANSFER_BODY;
ftp->downloadsize = 0;
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
diff --git a/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c
index d3720b1f1..716ff3817 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -424,7 +424,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
endptr++;
while(ISDIGIT(*endptr))
endptr++;
- if(*endptr != 0) {
+ if(*endptr) {
parser->error = CURLE_FTP_BAD_FILE_LIST;
goto fail;
}
@@ -966,7 +966,6 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
else if(c == '\n') {
parser->offsets.filename = parser->item_offset;
finfo->b_data[finfo->b_used - 1] = 0;
- parser->offsets.filename = parser->item_offset;
result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index 67ea07d2e..9091e6139 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -94,7 +94,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
{
switch(info) {
case CURLINFO_EFFECTIVE_URL:
- *param_charp = data->change.url?data->change.url:(char *)"";
+ *param_charp = data->state.url?data->state.url:(char *)"";
break;
case CURLINFO_EFFECTIVE_METHOD: {
const char *m = data->set.str[STRING_CUSTOMREQUEST];
@@ -145,6 +145,10 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
option had been enabled! */
*param_charp = data->info.wouldredirect;
break;
+ case CURLINFO_REFERER:
+ /* Return the referrer header for this request, or NULL if unset */
+ *param_charp = data->state.referer;
+ break;
case CURLINFO_PRIMARY_IP:
/* Return the ip address of the most recent (primary) connection */
*param_charp = data->info.conn_primary_ip;
@@ -235,7 +239,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
break;
#endif
case CURLINFO_REDIRECT_COUNT:
- *param_longp = data->set.followlocation;
+ *param_longp = data->state.followlocation;
break;
case CURLINFO_HTTPAUTH_AVAIL:
lptr.to_long = param_longp;
diff --git a/Utilities/cmcurl/lib/gopher.c b/Utilities/cmcurl/lib/gopher.c
index a39cc7e6b..f61232ff5 100644
--- a/Utilities/cmcurl/lib/gopher.c
+++ b/Utilities/cmcurl/lib/gopher.c
@@ -74,6 +74,7 @@ const struct Curl_handler Curl_handler_gopher = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_GOPHER, /* defport */
CURLPROTO_GOPHER, /* protocol */
CURLPROTO_GOPHER, /* family */
@@ -97,6 +98,7 @@ const struct Curl_handler Curl_handler_gophers = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_GOPHER, /* defport */
CURLPROTO_GOPHERS, /* protocol */
CURLPROTO_GOPHER, /* family */
diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index 5d433ad1f..12e7aa5f2 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -245,7 +245,7 @@ Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
struct Curl_hash_element *he = le->ptr;
lnext = le->next;
/* ask the callback function if we shall remove this entry or not */
- if(comp == NULL || comp(user, he->ptr)) {
+ if(!comp || comp(user, he->ptr)) {
Curl_llist_remove(list, le, (void *) h);
--h->size; /* one less entry in the hash now */
}
diff --git a/Utilities/cmcurl/lib/hostcheck.c b/Utilities/cmcurl/lib/hostcheck.c
index 0fef98b2a..49dbab347 100644
--- a/Utilities/cmcurl/lib/hostcheck.c
+++ b/Utilities/cmcurl/lib/hostcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -81,7 +81,7 @@ static int hostmatch(char *hostname, char *pattern)
pattern[len-1] = 0;
pattern_wildcard = strchr(pattern, '*');
- if(pattern_wildcard == NULL)
+ if(!pattern_wildcard)
return strcasecompare(pattern, hostname) ?
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
@@ -97,7 +97,7 @@ static int hostmatch(char *hostname, char *pattern)
match. */
wildcard_enabled = 1;
pattern_label_end = strchr(pattern, '.');
- if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL ||
+ if(!pattern_label_end || strchr(pattern_label_end + 1, '.') == NULL ||
pattern_wildcard > pattern_label_end ||
strncasecompare(pattern, "xn--", 4)) {
wildcard_enabled = 0;
@@ -107,7 +107,7 @@ static int hostmatch(char *hostname, char *pattern)
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
hostname_label_end = strchr(hostname, '.');
- if(hostname_label_end == NULL ||
+ if(!hostname_label_end ||
!strcasecompare(pattern_label_end, hostname_label_end))
return CURL_HOST_NOMATCH;
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index 8ba3fe81c..e0e3cfc2c 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -68,6 +68,10 @@
#include "curl_memory.h"
#include "memdebug.h"
+#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
+#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
+#endif
+
#if defined(CURLRES_SYNCH) && \
defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP)
/* alarm-based timeouts can only be used with all the dependencies satisfied */
@@ -269,7 +273,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
/* No entry found in cache, check if we might have a wildcard entry */
- if(!dns && data->change.wildcard_resolve) {
+ if(!dns && data->state.wildcard_resolve) {
create_hostcache_id("*", port, entry_id, sizeof(entry_id));
entry_len = strlen(entry_id);
@@ -466,10 +470,6 @@ Curl_cache_addr(struct Curl_easy *data,
* function is used. You MUST call Curl_resolv_unlock() later (when you're
* done using this struct) to decrease the counter again.
*
- * In debug mode, we specifically test for an interface name "LocalHost"
- * and resolve "localhost" instead as a means to permit test cases
- * to connect to a local test server with any host name.
- *
* Return codes:
*
* CURLRESOLV_ERROR (-1) = error, no pointer
@@ -520,13 +520,32 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
if(data->set.resolver_start) {
int st;
Curl_set_in_callback(data, true);
- st = data->set.resolver_start(data->state.async.resolver, NULL,
- data->set.resolver_start_client);
+ st = data->set.resolver_start(
+#ifdef USE_CURL_ASYNC
+ data->state.async.resolver,
+#else
+ NULL,
+#endif
+ NULL,
+ data->set.resolver_start_client);
Curl_set_in_callback(data, false);
if(st)
return CURLRESOLV_ERROR;
}
+#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
+ /*
+ * The automagic conversion from IPv4 literals to IPv6 literals only works
+ * if the SCDynamicStoreCopyProxies system function gets called first. As
+ * Curl currently doesn't support system-wide HTTP proxies, we therefore
+ * don't use any value this function might return.
+ *
+ * This function is only available on a macOS and is not needed for
+ * IPv4-only builds, hence the conditions above.
+ */
+ SCDynamicStoreCopyProxies(NULL);
+#endif
+
#ifndef USE_RESOLVE_ON_IPS
/* First check if this is an IPv4 address string */
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
@@ -572,13 +591,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
non-zero value indicating that we need to wait for the response to
the resolve call */
- addr = Curl_getaddrinfo(data,
-#ifdef DEBUGBUILD
- (data->set.str[STRING_DEVICE]
- && !strcmp(data->set.str[STRING_DEVICE],
- "LocalHost"))?"localhost":
-#endif
- hostname, port, &respwait);
+ addr = Curl_getaddrinfo(data, hostname, port, &respwait);
}
}
if(!addr) {
@@ -625,7 +638,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
* within a signal handler which is nonportable and could lead to problems.
*/
static
-RETSIGTYPE alarmfunc(int sig)
+void alarmfunc(int sig)
{
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void)sig;
@@ -872,9 +885,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
int port = 0;
/* Default is no wildcard found */
- data->change.wildcard_resolve = false;
+ data->state.wildcard_resolve = false;
- for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
+ for(hostp = data->state.resolve; hostp; hostp = hostp->next) {
char entry_id[MAX_HOSTCACHE_LEN];
if(!hostp->data)
continue;
@@ -1055,11 +1068,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(hostname[0] == '*' && hostname[1] == '\0') {
infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n",
hostname, port);
- data->change.wildcard_resolve = true;
+ data->state.wildcard_resolve = true;
}
}
}
- data->change.resolve = NULL; /* dealt with now */
+ data->state.resolve = NULL; /* dealt with now */
return CURLE_OK;
}
@@ -1102,10 +1115,12 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
CURLcode result;
struct connectdata *conn = data->conn;
+#ifdef USE_CURL_ASYNC
if(data->state.async.dns) {
conn->dns_entry = data->state.async.dns;
data->state.async.dns = NULL;
}
+#endif
result = Curl_setup_conn(data, protocol_done);
@@ -1116,3 +1131,34 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
}
return result;
}
+
+/*
+ * Curl_resolver_error() calls failf() with the appropriate message after a
+ * resolve error
+ */
+
+#ifdef USE_CURL_ASYNC
+CURLcode Curl_resolver_error(struct Curl_easy *data)
+{
+ const char *host_or_proxy;
+ CURLcode result;
+
+#ifndef CURL_DISABLE_PROXY
+ struct connectdata *conn = data->conn;
+ if(conn->bits.httpproxy) {
+ host_or_proxy = "proxy";
+ result = CURLE_COULDNT_RESOLVE_PROXY;
+ }
+ else
+#endif
+ {
+ host_or_proxy = "host";
+ result = CURLE_COULDNT_RESOLVE_HOST;
+ }
+
+ failf(data, "Could not resolve %s: %s", host_or_proxy,
+ data->state.async.hostname);
+
+ return result;
+}
+#endif /* USE_CURL_ASYNC */
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index c495c21e0..d178976aa 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -136,15 +136,6 @@ void Curl_hostcache_prune(struct Curl_easy *data);
/* Return # of addresses in a Curl_addrinfo struct */
int Curl_num_addresses(const struct Curl_addrinfo *addr);
-#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
-int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
- GETNAMEINFO_TYPE_ARG2 salen,
- char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
- char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
- GETNAMEINFO_TYPE_ARG7 flags,
- int line, const char *source);
-#endif
-
/* IPv4 threadsafe resolve function used for synch and asynch builds */
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
@@ -245,4 +236,5 @@ CURLcode Curl_resolv_check(struct Curl_easy *data,
int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks);
+CURLcode Curl_resolver_error(struct Curl_easy *data);
#endif /* HEADER_CURL_HOSTIP_H */
diff --git a/Utilities/cmcurl/lib/hostip6.c b/Utilities/cmcurl/lib/hostip6.c
index 53b3c6722..9791d8646 100644
--- a/Utilities/cmcurl/lib/hostip6.c
+++ b/Utilities/cmcurl/lib/hostip6.c
@@ -140,26 +140,13 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
#ifndef USE_RESOLVE_ON_IPS
char addrbuf[128];
#endif
- int pf;
+ int pf = PF_INET;
*waitp = 0; /* synchronous response only */
- /* Check if a limited name resolve has been requested */
- switch(data->set.ipver) {
- case CURL_IPRESOLVE_V4:
- pf = PF_INET;
- break;
- case CURL_IPRESOLVE_V6:
- pf = PF_INET6;
- break;
- default:
+ if(Curl_ipv6works(data))
+ /* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
- break;
- }
-
- if((pf != PF_INET) && !Curl_ipv6works(data))
- /* The stack seems to be a non-IPv6 one */
- pf = PF_INET;
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
diff --git a/Utilities/cmcurl/lib/hsts.c b/Utilities/cmcurl/lib/hsts.c
index 0e7c19cfb..ef166f196 100644
--- a/Utilities/cmcurl/lib/hsts.c
+++ b/Utilities/cmcurl/lib/hsts.c
@@ -25,7 +25,7 @@
*/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS)
#include <curl/curl.h>
#include "urldata.h"
#include "llist.h"
@@ -37,6 +37,7 @@
#include "parsedate.h"
#include "rand.h"
#include "rename.h"
+#include "strtoofft.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -46,8 +47,6 @@
#define MAX_HSTS_LINE 4095
#define MAX_HSTS_HOSTLEN 256
#define MAX_HSTS_HOSTLENSTR "256"
-#define MAX_HSTS_SUBLEN 4
-#define MAX_HSTS_SUBLENSTR "4"
#define MAX_HSTS_DATELEN 64
#define MAX_HSTS_DATELENSTR "64"
@@ -60,7 +59,10 @@ static time_t debugtime(void *unused)
char *timestr = getenv("CURL_TIME");
(void)unused;
if(timestr) {
- unsigned long val = strtol(timestr, NULL, 10) + deltatime;
+ curl_off_t val;
+ (void)curlx_strtoofft(timestr, NULL, 10, &val);
+
+ val += (curl_off_t)deltatime;
return (time_t)val;
}
return time(NULL);
@@ -276,7 +278,7 @@ static CURLcode hsts_push(struct Curl_easy *data,
e.namelen = strlen(sts->host);
e.includeSubDomains = sts->includeSubDomains;
- result = Curl_gmtime(sts->expires, &stamp);
+ result = Curl_gmtime((time_t)sts->expires, &stamp);
if(result)
return result;
@@ -296,7 +298,7 @@ static CURLcode hsts_push(struct Curl_easy *data,
static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
{
struct tm stamp;
- CURLcode result = Curl_gmtime(sts->expires, &stamp);
+ CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp);
if(result)
return result;
@@ -441,7 +443,10 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
expires = Curl_getdate_capped(e.expire);
else
expires = TIME_T_MAX; /* the end of time */
- result = hsts_create(h, e.name, e.includeSubDomains, expires);
+ result = hsts_create(h, e.name,
+ /* bitfield to bool conversion: */
+ e.includeSubDomains ? TRUE : FALSE,
+ expires);
if(result)
return result;
}
@@ -519,4 +524,4 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
return hsts_pull(data, h);
}
-#endif /* CURL_DISABLE_HTTP || USE_HSTS */
+#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
diff --git a/Utilities/cmcurl/lib/hsts.h b/Utilities/cmcurl/lib/hsts.h
index ae5db74a2..baa582864 100644
--- a/Utilities/cmcurl/lib/hsts.h
+++ b/Utilities/cmcurl/lib/hsts.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2020 - 2021, 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
@@ -23,7 +23,7 @@
***************************************************************************/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS)
#include <curl/curl.h>
#include "llist.h"
@@ -35,7 +35,7 @@ struct stsentry {
struct Curl_llist_element node;
const char *host;
bool includeSubDomains;
- time_t expires; /* the timestamp of this entry's expiry */
+ curl_off_t expires; /* the timestamp of this entry's expiry */
};
/* The HSTS cache. Needs to be able to tailmatch host names. */
@@ -61,5 +61,5 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data,
#define Curl_hsts_cleanup(x)
#define Curl_hsts_loadcb(x,y)
#define Curl_hsts_save(x,y,z)
-#endif /* CURL_DISABLE_HTTP || USE_HSTS */
+#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
#endif /* HEADER_CURL_HSTS_H */
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index 6f7f55d07..628dd7370 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -133,6 +133,7 @@ const struct Curl_handler Curl_handler_http = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
CURLPROTO_HTTP, /* family */
@@ -160,6 +161,7 @@ const struct Curl_handler Curl_handler_https = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
CURLPROTO_HTTP, /* family */
@@ -183,7 +185,7 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
Curl_mime_initpart(&http->form, data);
data->req.p.http = http;
- if(data->set.httpversion == CURL_HTTP_VERSION_3) {
+ if(data->state.httpwant == CURL_HTTP_VERSION_3) {
if(conn->handler->flags & PROTOPT_SSL)
/* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
the QUIC dance. */
@@ -298,26 +300,27 @@ static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
{
size_t size = 0;
char *authorization = NULL;
- struct connectdata *conn = data->conn;
char **userp;
const char *user;
const char *pwd;
CURLcode result;
char *out;
+ /* credentials are unique per transfer for HTTP, do not use the ones for the
+ connection */
if(proxy) {
#ifndef CURL_DISABLE_PROXY
userp = &data->state.aptr.proxyuserpwd;
- user = conn->http_proxy.user;
- pwd = conn->http_proxy.passwd;
+ user = data->state.aptr.proxyuser;
+ pwd = data->state.aptr.proxypasswd;
#else
return CURLE_NOT_BUILT_IN;
#endif
}
else {
userp = &data->state.aptr.userpwd;
- user = conn->user;
- pwd = conn->passwd;
+ user = data->state.aptr.user;
+ pwd = data->state.aptr.passwd;
}
out = aprintf("%s:%s", user, pwd ? pwd : "");
@@ -595,7 +598,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
conn->httpversion > 11) {
infof(data, "Forcing HTTP/1.1 for NTLM");
connclose(conn, "Force HTTP/1.1 connection");
- data->set.httpversion = CURL_HTTP_VERSION_1_1;
+ data->state.httpwant = CURL_HTTP_VERSION_1_1;
}
}
#ifndef CURL_DISABLE_PROXY
@@ -621,7 +624,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
we must make sure to free it before allocating a new one. As figured
out in bug #2284386 */
Curl_safefree(data->req.newurl);
- data->req.newurl = strdup(data->change.url); /* clone URL */
+ data->req.newurl = strdup(data->state.url); /* clone URL */
if(!data->req.newurl)
return CURLE_OUT_OF_MEMORY;
}
@@ -634,7 +637,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
we didn't try HEAD or GET */
if((data->state.httpreq != HTTPREQ_GET) &&
(data->state.httpreq != HTTPREQ_HEAD)) {
- data->req.newurl = strdup(data->change.url); /* clone URL */
+ data->req.newurl = strdup(data->state.url); /* clone URL */
if(!data->req.newurl)
return CURLE_OUT_OF_MEMORY;
data->state.authhost.done = TRUE;
@@ -709,7 +712,6 @@ output_auth_headers(struct Curl_easy *data,
if(authstatus->picked == CURLAUTH_DIGEST) {
auth = "Digest";
result = Curl_output_digest(data,
- conn,
proxy,
(const unsigned char *)request,
(const unsigned char *)path);
@@ -740,7 +742,7 @@ output_auth_headers(struct Curl_easy *data,
if(authstatus->picked == CURLAUTH_BEARER) {
/* Bearer */
if((!proxy && data->set.str[STRING_BEARER] &&
- !Curl_checkheaders(data, "Authorization:"))) {
+ !Curl_checkheaders(data, "Authorization"))) {
auth = "Bearer";
result = http_output_bearer(data);
if(result)
@@ -756,11 +758,14 @@ output_auth_headers(struct Curl_easy *data,
#ifndef CURL_DISABLE_PROXY
infof(data, "%s auth using %s with user '%s'\n",
proxy ? "Proxy" : "Server", auth,
- proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") :
- (conn->user ? conn->user : ""));
+ proxy ? (data->state.aptr.proxyuser ?
+ data->state.aptr.proxyuser : "") :
+ (data->state.aptr.user ?
+ data->state.aptr.user : ""));
#else
infof(data, "Server auth using %s with user '%s'\n",
- auth, conn->user ? conn->user : "");
+ auth, data->state.aptr.user ?
+ data->state.aptr.user : "");
#endif
authstatus->multipass = (!authstatus->done) ? TRUE : FALSE;
}
@@ -871,13 +876,17 @@ Curl_http_output_auth(struct Curl_easy *data,
#else
/* when disabled */
CURLcode
-Curl_http_output_auth(struct connectdata *conn,
+Curl_http_output_auth(struct Curl_easy *data,
+ struct connectdata *conn,
const char *request,
+ Curl_HttpReq httpreq,
const char *path,
bool proxytunnel)
{
+ (void)data;
(void)conn;
(void)request;
+ (void)httpreq;
(void)path;
(void)proxytunnel;
return CURLE_OK;
@@ -890,6 +899,11 @@ Curl_http_output_auth(struct connectdata *conn,
* proxy CONNECT loop.
*/
+static int is_valid_auth_separator(char ch)
+{
+ return ch == '\0' || ch == ',' || ISSPACE(ch);
+}
+
CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth) /* the first non-space */
{
@@ -933,7 +947,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
while(*auth) {
#ifdef USE_SPNEGO
- if(checkprefix("Negotiate", auth)) {
+ if(checkprefix("Negotiate", auth) && is_valid_auth_separator(auth[9])) {
if((authp->avail & CURLAUTH_NEGOTIATE) ||
Curl_auth_is_spnego_supported()) {
*availp |= CURLAUTH_NEGOTIATE;
@@ -943,7 +957,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
CURLcode result = Curl_input_negotiate(data, conn, proxy, auth);
if(!result) {
DEBUGASSERT(!data->req.newurl);
- data->req.newurl = strdup(data->change.url);
+ data->req.newurl = strdup(data->state.url);
if(!data->req.newurl)
return CURLE_OUT_OF_MEMORY;
data->state.authproblem = FALSE;
@@ -959,7 +973,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
#endif
#ifdef USE_NTLM
/* NTLM support requires the SSL crypto libs */
- if(checkprefix("NTLM", auth)) {
+ if(checkprefix("NTLM", auth) && is_valid_auth_separator(auth[4])) {
if((authp->avail & CURLAUTH_NTLM) ||
(authp->avail & CURLAUTH_NTLM_WB) ||
Curl_auth_is_ntlm_supported()) {
@@ -997,7 +1011,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
else
#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH
- if(checkprefix("Digest", auth)) {
+ if(checkprefix("Digest", auth) && is_valid_auth_separator(auth[6])) {
if((authp->avail & CURLAUTH_DIGEST) != 0)
infof(data, "Ignoring duplicate digest auth header.\n");
else if(Curl_auth_is_digest_supported()) {
@@ -1019,7 +1033,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
}
else
#endif
- if(checkprefix("Basic", auth)) {
+ if(checkprefix("Basic", auth) &&
+ is_valid_auth_separator(auth[5])) {
*availp |= CURLAUTH_BASIC;
authp->avail |= CURLAUTH_BASIC;
if(authp->picked == CURLAUTH_BASIC) {
@@ -1032,7 +1047,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
}
}
else
- if(checkprefix("Bearer", auth)) {
+ if(checkprefix("Bearer", auth) &&
+ is_valid_auth_separator(auth[6])) {
*availp |= CURLAUTH_BEARER;
authp->avail |= CURLAUTH_BEARER;
if(authp->picked == CURLAUTH_BEARER) {
@@ -1088,6 +1104,14 @@ static bool http_should_fail(struct Curl_easy *data)
return FALSE;
/*
+ ** A 416 response to a resume request is presumably because the file is
+ ** already completely downloaded and thus not actually a fail.
+ */
+ if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
+ httpcode == 416)
+ return FALSE;
+
+ /*
** Any code >= 400 that's not 401 or 407 is always
** a terminal error
*/
@@ -1152,7 +1176,12 @@ static size_t readmoredata(char *buffer,
/* make sure that a HTTP request is never sent away chunked! */
data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
- if(http->postsize <= (curl_off_t)fullsize) {
+ if(data->set.max_send_speed &&
+ (data->set.max_send_speed < http->postsize))
+ /* speed limit */
+ fullsize = (size_t)data->set.max_send_speed;
+
+ else if(http->postsize <= (curl_off_t)fullsize) {
memcpy(buffer, http->postdata, (size_t)http->postsize);
fullsize = (size_t)http->postsize;
@@ -1192,7 +1221,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
counter */
curl_off_t *bytes_written,
/* how much of the buffer contains body data */
- size_t included_body_bytes,
+ curl_off_t included_body_bytes,
int socketindex)
{
ssize_t amount;
@@ -1215,10 +1244,10 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
ptr = Curl_dyn_ptr(in);
size = Curl_dyn_len(in);
- headersize = size - included_body_bytes; /* the initial part that isn't body
- is header */
+ headersize = size - (size_t)included_body_bytes; /* the initial part that
+ isn't body is header */
- DEBUGASSERT(size > included_body_bytes);
+ DEBUGASSERT(size > (size_t)included_body_bytes);
result = Curl_convert_to_network(data, ptr, headersize);
/* Curl_convert_to_network calls failf if unsuccessful */
@@ -1234,13 +1263,17 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
#endif
)
&& conn->httpversion != 20) {
- /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
- when we speak HTTPS, as if only a fraction of it is sent now, this data
- needs to fit into the normal read-callback buffer later on and that
- buffer is using this size.
+ /* Make sure this doesn't send more body bytes than what the max send
+ speed says. The request bytes do not count to the max speed.
*/
-
- sendsize = CURLMIN(size, CURL_MAX_WRITE_SIZE);
+ if(data->set.max_send_speed &&
+ (included_body_bytes > data->set.max_send_speed)) {
+ curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
+ DEBUGASSERT((size_t)overflow < size);
+ sendsize = size - (size_t)overflow;
+ }
+ else
+ sendsize = size;
/* OpenSSL is very picky and we must send the SAME buffer pointer to the
library when we attempt to re-send this buffer. Sending the same data
@@ -1254,6 +1287,14 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
Curl_dyn_free(in);
return result;
}
+ /* We never send more than upload_buffer_size bytes in one single chunk
+ when we speak HTTPS, as if only a fraction of it is sent now, this data
+ needs to fit into the normal read-callback buffer later on and that
+ buffer is using this size.
+ */
+ if(sendsize > (size_t)data->set.upload_buffer_size)
+ sendsize = (size_t)data->set.upload_buffer_size;
+
memcpy(data->state.ulbuf, ptr, sendsize);
ptr = data->state.ulbuf;
}
@@ -1272,7 +1313,19 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
}
else
#endif
- sendsize = size;
+ {
+ /* Make sure this doesn't send more body bytes than what the max send
+ speed says. The request bytes do not count to the max speed.
+ */
+ if(data->set.max_send_speed &&
+ (included_body_bytes > data->set.max_send_speed)) {
+ curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
+ DEBUGASSERT((size_t)overflow < size);
+ sendsize = size - (size_t)overflow;
+ }
+ else
+ sendsize = size;
+ }
}
result = Curl_write(data, sockfd, ptr, sendsize, &amount);
@@ -1500,7 +1553,7 @@ static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
msnprintf(proxy_header,
sizeof(proxy_header),
- "PROXY %s %s %s %li %li\r\n",
+ "PROXY %s %s %s %i %i\r\n",
tcp_version,
data->info.conn_local_ip,
data->info.conn_primary_ip,
@@ -1548,7 +1601,7 @@ static int https_getsock(struct Curl_easy *data,
{
(void)data;
if(conn->handler->flags & PROTOPT_SSL)
- return Curl_ssl_getsock(conn, socks);
+ return Curl_ssl->getsock(conn, socks);
return GETSOCK_BLANK;
}
#endif /* USE_SSL */
@@ -1621,11 +1674,11 @@ static bool use_http_1_1plus(const struct Curl_easy *data,
{
if((data->state.httpversion == 10) || (conn->httpversion == 10))
return FALSE;
- if((data->set.httpversion == CURL_HTTP_VERSION_1_0) &&
+ if((data->state.httpwant == CURL_HTTP_VERSION_1_0) &&
(conn->httpversion <= 10))
return FALSE;
- return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) ||
- (data->set.httpversion >= CURL_HTTP_VERSION_1_1));
+ return ((data->state.httpwant == CURL_HTTP_VERSION_NONE) ||
+ (data->state.httpwant >= CURL_HTTP_VERSION_1_1));
}
#ifndef USE_HYPER
@@ -1633,7 +1686,7 @@ static const char *get_http_string(const struct Curl_easy *data,
const struct connectdata *conn)
{
#ifdef ENABLE_QUIC
- if((data->set.httpversion == CURL_HTTP_VERSION_3) ||
+ if((data->state.httpwant == CURL_HTTP_VERSION_3) ||
(conn->httpversion == 30))
return "3";
#endif
@@ -1698,7 +1751,7 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
if(
#ifdef CURL_DO_LINEEND_CONV
- (handle->set.prefer_ascii) ||
+ (handle->state.prefer_ascii) ||
#endif
(handle->set.crlf)) {
/* \n will become \r\n later on */
@@ -1960,10 +2013,10 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
}
#else
/* disabled */
-CURLcode Curl_add_timecondition(const struct connectdata *conn,
+CURLcode Curl_add_timecondition(struct Curl_easy *data,
struct dynbuf *req)
{
- (void)conn;
+ (void)data;
(void)req;
return CURLE_OK;
}
@@ -2174,7 +2227,7 @@ CURLcode Curl_http_target(struct Curl_easy *data,
/* Extract the URL to use in the request. Store in STRING_TEMP_URL for
clean-up reasons if the function returns before the free() further
down. */
- uc = curl_url_get(h, CURLUPART_URL, &url, 0);
+ uc = curl_url_get(h, CURLUPART_URL, &url, CURLU_NO_DEFAULT_PORT);
if(uc) {
curl_url_cleanup(h);
return CURLE_OUT_OF_MEMORY;
@@ -2205,7 +2258,7 @@ CURLcode Curl_http_target(struct Curl_easy *data,
}
if(!type) {
result = Curl_dyn_addf(r, ";type=%c",
- data->set.prefer_ascii ? 'a' : 'i');
+ data->state.prefer_ascii ? 'a' : 'i');
if(result)
return result;
}
@@ -2614,8 +2667,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
}
}
/* issue the request */
- result = Curl_buffer_send(r, data, &data->info.request_size,
- (size_t)included_body, FIRSTSOCKET);
+ result = Curl_buffer_send(r, data, &data->info.request_size, included_body,
+ FIRSTSOCKET);
if(result)
failf(data, "Failed sending HTTP POST request");
@@ -2946,7 +2999,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
default:
/* Check if user wants to use HTTP/2 with clear TCP*/
#ifdef USE_NGHTTP2
- if(data->set.httpversion == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+ if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
/* We don't support HTTP/2 proxies yet. Also it's debatable
@@ -3002,8 +3055,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
}
Curl_safefree(data->state.aptr.ref);
- if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
- data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ if(data->state.referer && !Curl_checkheaders(data, "Referer")) {
+ data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
if(!data->state.aptr.ref)
return CURLE_OUT_OF_MEMORY;
}
@@ -3016,10 +3069,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(!data->state.aptr.accept_encoding)
return CURLE_OUT_OF_MEMORY;
}
- else {
+ else
Curl_safefree(data->state.aptr.accept_encoding);
- data->state.aptr.accept_encoding = NULL;
- }
#ifdef HAVE_LIBZ
/* we only consider transfer-encoding magic if libz support is built-in */
@@ -3071,6 +3122,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
/* initialize a dynamic send-buffer */
Curl_dyn_init(&req, DYN_HTTP_REQUEST);
+ /* make sure the header buffer is reset - if there are leftovers from a
+ previous transfer */
+ Curl_dyn_reset(&data->state.headerb);
+
/* add the main request stuff */
/* GET/HEAD/POST/PUT */
result = Curl_dyn_addf(&req, "%s ", request);
@@ -3124,7 +3179,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
*data->set.str[STRING_ENCODING] &&
data->state.aptr.accept_encoding)?
data->state.aptr.accept_encoding:"",
- (data->change.referer && data->state.aptr.ref)?
+ (data->state.referer && data->state.aptr.ref)?
data->state.aptr.ref:"" /* Referer: <data> */,
#ifndef CURL_DISABLE_PROXY
(conn->bits.httpproxy &&
@@ -3152,10 +3207,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(!(conn->handler->flags&PROTOPT_SSL) &&
conn->httpversion != 20 &&
- (data->set.httpversion == CURL_HTTP_VERSION_2)) {
+ (data->state.httpwant == CURL_HTTP_VERSION_2)) {
/* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
over SSL */
- result = Curl_http2_request_upgrade(&req, conn);
+ result = Curl_http2_request_upgrade(&req, data);
if(result) {
Curl_dyn_free(&req);
return result;
@@ -3333,7 +3388,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
if(!k->http_bodyless &&
!data->set.ignorecl && checkprefix("Content-Length:", headp)) {
curl_off_t contentlength;
- CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength);
+ CURLofft offt = curlx_strtoofft(headp + strlen("Content-Length:"),
+ NULL, 10, &contentlength);
if(offt == CURL_OFFT_OK) {
if(data->set.max_filesize &&
@@ -3432,7 +3488,9 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
* of chunks, and a chunk-data set to zero signals the
* end-of-chunks. */
- result = Curl_build_unencoding_stack(data, headp + 18, TRUE);
+ result = Curl_build_unencoding_stack(data,
+ headp + strlen("Transfer-Encoding:"),
+ TRUE);
if(result)
return result;
}
@@ -3445,17 +3503,20 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
* 2616). zlib cannot handle compress. However, errors are
* handled further down when the response body is processed
*/
- result = Curl_build_unencoding_stack(data, headp + 17, FALSE);
+ result = Curl_build_unencoding_stack(data,
+ headp + strlen("Content-Encoding:"),
+ FALSE);
if(result)
return result;
}
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[12]);
+ 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[12], NULL, 10, &retry_after);
+ (void)curlx_strtoofft(headp + strlen("Retry-After:"),
+ NULL, 10, &retry_after);
}
else
/* convert date to number of seconds into the future */
@@ -3474,7 +3535,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
The forth means the requested range was unsatisfied.
*/
- char *ptr = headp + 14;
+ char *ptr = headp + strlen("Content-Range:");
/* Move forward until first digit or asterisk */
while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
@@ -3497,7 +3558,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_add(data,
- data->cookies, TRUE, FALSE, headp + 11,
+ data->cookies, TRUE, FALSE,
+ headp + strlen("Set-Cookie:"),
/* If there is a custom-set Host: name, use it
here, or else use real peer host name. */
data->state.aptr.cookiehost?
@@ -3532,7 +3594,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
return result;
}
#ifdef USE_SPNEGO
- else if(checkprefix("Persistent-Auth", headp)) {
+ else if(checkprefix("Persistent-Auth:", headp)) {
struct negotiatedata *negdata = &conn->negotiate;
struct auth *authp = &data->state.authhost;
if(authp->picked == CURLAUTH_NEGOTIATE) {
@@ -3576,13 +3638,13 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
}
}
-#ifdef USE_HSTS
+#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)) {
CURLcode check =
Curl_hsts_parse(data->hsts, data->state.up.hostname,
- &headp[ sizeof("Strict-Transport-Security:") -1 ]);
+ headp + strlen("Strict-Transport-Security:"));
if(check)
infof(data, "Illegal STS header skipped\n");
#ifdef DEBUGBUILD
@@ -3606,7 +3668,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
/* the ALPN of the current request */
enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
result = Curl_altsvc_parse(data, data->asi,
- &headp[ strlen("Alt-Svc:") ],
+ headp + strlen("Alt-Svc:"),
id, conn->host.name,
curlx_uitous(conn->remote_port));
if(result)
@@ -3995,7 +4057,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
infof(data, "Got 417 while waiting for a 100\n");
data->state.disableexpect = TRUE;
DEBUGASSERT(!data->req.newurl);
- data->req.newurl = strdup(data->change.url);
+ data->req.newurl = strdup(data->state.url);
Curl_done_sending(data, k);
}
else if(data->set.http_keep_sending_on_error) {
@@ -4144,10 +4206,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
*/
char separator;
char twoorthree[2];
+ int httpversion = 0;
nc = sscanf(HEADER1,
" HTTP/%1d.%1d%c%3d",
&httpversion_major,
- &conn->httpversion,
+ &httpversion,
&separator,
&k->httpcode);
@@ -4159,7 +4222,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
if((nc == 4) && (' ' == separator)) {
- conn->httpversion += 10 * httpversion_major;
+ httpversion += 10 * httpversion_major;
+ switch(httpversion) {
+ case 10:
+ case 11:
+#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+ case 20:
+#endif
+#if defined(ENABLE_QUIC)
+ case 30:
+#endif
+ conn->httpversion = (unsigned char)httpversion;
+ break;
+ default:
+ failf(data, "Unsupported HTTP version (%u.%d) in response",
+ httpversion/10, httpversion%10);
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
if(k->upgr101 == UPGR101_RECEIVED) {
/* supposedly upgraded to http2 now */
@@ -4200,14 +4279,14 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
else if(conn->handler->protocol & CURLPROTO_RTSP) {
char separator;
+ int rtspversion;
nc = sscanf(HEADER1,
" RTSP/%1d.%1d%c%3d",
&rtspversion_major,
- &conn->rtspversion,
+ &rtspversion,
&separator,
&k->httpcode);
if((nc == 4) && (' ' == separator)) {
- conn->rtspversion += 10 * rtspversion_major;
conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
}
else {
diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h
index 28f9341f6..2a3834ae1 100644
--- a/Utilities/cmcurl/lib/http.h
+++ b/Utilities/cmcurl/lib/http.h
@@ -58,7 +58,7 @@ char *Curl_checkProxyheaders(struct Curl_easy *data,
CURLcode Curl_buffer_send(struct dynbuf *in,
struct Curl_easy *data,
curl_off_t *bytes_written,
- size_t included_body_bytes,
+ curl_off_t included_body_bytes,
int socketindex);
#else
#define Curl_buffer_send(a,b,c,d,e) CURLE_OK
@@ -184,8 +184,7 @@ struct HTTP {
enum {
HTTPSEND_NADA, /* init */
HTTPSEND_REQUEST, /* sending a request */
- HTTPSEND_BODY, /* sending body */
- HTTPSEND_LAST /* never use this */
+ HTTPSEND_BODY /* sending body */
} sending;
#ifndef CURL_DISABLE_HTTP
@@ -211,6 +210,7 @@ struct HTTP {
char **push_headers; /* allocated array */
size_t push_headers_used; /* number of entries filled in */
size_t push_headers_alloc; /* number of entries allocated */
+ uint32_t error; /* HTTP/2 stream error code */
#endif
#if defined(USE_NGHTTP2) || defined(USE_NGHTTP3)
bool closed; /* TRUE on HTTP2 stream close */
@@ -251,9 +251,16 @@ struct h2settings {
struct http_conn {
#ifdef USE_NGHTTP2
#define H2_BINSETTINGS_LEN 80
- nghttp2_session *h2;
uint8_t binsettings[H2_BINSETTINGS_LEN];
size_t binlen; /* length of the binsettings data */
+
+ /* We associate the connnectdata struct with the connection, but we need to
+ make sure we can identify the current "driving" transfer. This is a
+ work-around for the lack of nghttp2_session_set_user_data() in older
+ nghttp2 versions that we want to support. (Added in 1.31.0) */
+ struct Curl_easy *trnsfr;
+
+ nghttp2_session *h2;
Curl_send *send_underlying; /* underlying send Curl_send callback */
Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */
char *inbuf; /* buffer to receive data from underlying socket */
@@ -274,7 +281,6 @@ struct http_conn {
/* list of settings that will be sent */
nghttp2_settings_entry local_settings[3];
size_t local_settings_num;
- uint32_t error_code; /* HTTP/2 error code */
#else
int unused; /* prevent a compiler warning */
#endif
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index be4c71242..f194c18b2 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -211,6 +211,24 @@ static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn)
return dead;
}
+/*
+ * Set the transfer that is currently using this HTTP/2 connection.
+ */
+static void set_transfer(struct http_conn *c,
+ struct Curl_easy *data)
+{
+ c->trnsfr = data;
+}
+
+/*
+ * Get the transfer that is currently using this HTTP/2 connection.
+ */
+static struct Curl_easy *get_transfer(struct http_conn *c)
+{
+ DEBUGASSERT(c && c->trnsfr);
+ return c->trnsfr;
+}
+
static unsigned int http2_conncheck(struct Curl_easy *data,
struct connectdata *conn,
unsigned int checks_to_perform)
@@ -247,6 +265,7 @@ static unsigned int http2_conncheck(struct Curl_easy *data,
}
if(send_frames) {
+ set_transfer(c, data); /* set the transfer */
rc = nghttp2_session_send(c->h2);
if(rc)
failf(data, "nghttp2_session_send() failed: %s(%d)",
@@ -269,6 +288,7 @@ void Curl_http2_setup_req(struct Curl_easy *data)
http->mem = NULL;
http->len = 0;
http->memlen = 0;
+ http->error = NGHTTP2_NO_ERROR;
}
/* called from http_setup_conn */
@@ -276,7 +296,6 @@ void Curl_http2_setup_conn(struct connectdata *conn)
{
conn->proto.httpc.settings.max_concurrent_streams =
DEFAULT_MAX_CONCURRENT_STREAMS;
- conn->proto.httpc.error_code = NGHTTP2_NO_ERROR;
}
/*
@@ -300,6 +319,7 @@ static const struct Curl_handler Curl_handler_http2 = {
http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
http2_conncheck, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
CURLPROTO_HTTP, /* family */
@@ -322,6 +342,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
http2_conncheck, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
CURLPROTO_HTTP, /* family */
@@ -349,6 +370,7 @@ static ssize_t send_callback(nghttp2_session *h2,
{
struct connectdata *conn = (struct connectdata *)userp;
struct http_conn *c = &conn->proto.httpc;
+ struct Curl_easy *data = get_transfer(c);
ssize_t written;
CURLcode result = CURLE_OK;
@@ -359,7 +381,7 @@ static ssize_t send_callback(nghttp2_session *h2,
/* called before setup properly! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- written = ((Curl_send*)c->send_underlying)(conn->data, FIRSTSOCKET,
+ written = ((Curl_send*)c->send_underlying)(data, FIRSTSOCKET,
mem, length, &result);
if(result == CURLE_AGAIN) {
@@ -367,7 +389,7 @@ static ssize_t send_callback(nghttp2_session *h2,
}
if(written == -1) {
- failf(conn->data, "Failed sending HTTP2 data");
+ failf(data, "Failed sending HTTP2 data");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@@ -479,38 +501,48 @@ static int set_transfer_url(struct Curl_easy *data,
const char *v;
CURLU *u = curl_url();
CURLUcode uc;
- char *url;
+ char *url = NULL;
+ int rc = 0;
v = curl_pushheader_byname(hp, ":scheme");
if(v) {
uc = curl_url_set(u, CURLUPART_SCHEME, v, 0);
- if(uc)
- return 1;
+ if(uc) {
+ rc = 1;
+ goto fail;
+ }
}
v = curl_pushheader_byname(hp, ":authority");
if(v) {
uc = curl_url_set(u, CURLUPART_HOST, v, 0);
- if(uc)
- return 2;
+ if(uc) {
+ rc = 2;
+ goto fail;
+ }
}
v = curl_pushheader_byname(hp, ":path");
if(v) {
uc = curl_url_set(u, CURLUPART_PATH, v, 0);
- if(uc)
- return 3;
+ if(uc) {
+ rc = 3;
+ goto fail;
+ }
}
uc = curl_url_get(u, CURLUPART_URL, &url, 0);
if(uc)
- return 4;
+ rc = 4;
+ fail:
curl_url_cleanup(u);
+ if(rc)
+ return rc;
- if(data->change.url_alloc)
- free(data->change.url);
- data->change.url_alloc = TRUE;
- data->change.url = url;
+ if(data->state.url_alloc)
+ free(data->state.url);
+ data->state.url_alloc = TRUE;
+ data->state.url = url;
return 0;
}
@@ -551,6 +583,7 @@ static int push_promise(struct Curl_easy *data,
rv = set_transfer_url(newhandle, &heads);
if(rv) {
+ (void)Curl_close(&newhandle);
rv = CURL_PUSH_DENY;
goto fail;
}
@@ -633,6 +666,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
struct http_conn *httpc = &conn->proto.httpc;
struct Curl_easy *data_s = NULL;
struct HTTP *stream = NULL;
+ struct Curl_easy *data = get_transfer(httpc);
int rv;
size_t left, ncopy;
int32_t stream_id = frame->hd.stream_id;
@@ -642,30 +676,30 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
/* stream ID zero is for connection-oriented stuff */
if(frame->hd.type == NGHTTP2_SETTINGS) {
uint32_t max_conn = httpc->settings.max_concurrent_streams;
- H2BUGF(infof(conn->data, "Got SETTINGS\n"));
+ H2BUGF(infof(data, "Got SETTINGS\n"));
httpc->settings.max_concurrent_streams =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
httpc->settings.enable_push =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_ENABLE_PUSH);
- H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
+ H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d\n",
httpc->settings.max_concurrent_streams));
- H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
+ H2BUGF(infof(data, "ENABLE_PUSH == %s\n",
httpc->settings.enable_push?"TRUE":"false"));
if(max_conn != httpc->settings.max_concurrent_streams) {
/* only signal change if the value actually changed */
- infof(conn->data,
+ infof(data,
"Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
httpc->settings.max_concurrent_streams);
- multi_connchanged(conn->data->multi);
+ multi_connchanged(data->multi);
}
}
return 0;
}
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
if(!data_s) {
- H2BUGF(infof(conn->data,
+ H2BUGF(infof(data,
"No Curl_easy associated with stream: %x\n",
stream_id));
return 0;
@@ -733,14 +767,9 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
stream->memlen += ncopy;
drain_this(data_s, httpc);
- {
- /* get the pointer from userp again since it was re-assigned above */
- struct connectdata *conn_s = (struct connectdata *)userp;
-
- /* if we receive data for another handle, wake that up */
- if(conn_s->data != data_s)
- Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- }
+ /* if we receive data for another handle, wake that up */
+ if(get_transfer(httpc) != data_s)
+ Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
break;
case NGHTTP2_PUSH_PROMISE:
rv = push_promise(data_s, conn, &frame->push_promise);
@@ -768,15 +797,15 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
- const uint8_t *data, size_t len, void *userp)
+ const uint8_t *mem, size_t len, void *userp)
{
struct HTTP *stream;
struct Curl_easy *data_s;
size_t nread;
struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *httpc = &conn->proto.httpc;
(void)session;
(void)flags;
- (void)data;
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
@@ -792,7 +821,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
return NGHTTP2_ERR_CALLBACK_FAILURE;
nread = CURLMIN(stream->len, len);
- memcpy(&stream->mem[stream->memlen], data, nread);
+ memcpy(&stream->mem[stream->memlen], mem, nread);
stream->len -= nread;
stream->memlen += nread;
@@ -800,7 +829,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
drain_this(data_s, &conn->proto.httpc);
/* if we receive data for another handle, wake that up */
- if(conn->data != data_s)
+ if(get_transfer(httpc) != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
H2BUGF(infof(data_s, "%zu data received for stream %u "
@@ -810,7 +839,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
stream->memlen));
if(nread < len) {
- stream->pausedata = data + nread;
+ stream->pausedata = mem + nread;
stream->pauselen = len - nread;
H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
", stream %u\n",
@@ -822,7 +851,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
/* pause execution of nghttp2 if we received data for another handle
in order to process them first. */
- if(conn->data != data_s) {
+ if(get_transfer(httpc) != data_s) {
data_s->conn->proto.httpc.pause_stream_id = stream_id;
return NGHTTP2_ERR_PAUSE;
@@ -861,7 +890,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
httpc = &conn->proto.httpc;
drain_this(data_s, httpc);
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- httpc->error_code = error_code;
+ stream->error = error_code;
/* remove the entry from the hash as the stream is now gone */
rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
@@ -944,6 +973,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
struct Curl_easy *data_s;
int32_t stream_id = frame->hd.stream_id;
struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *httpc = &conn->proto.httpc;
CURLcode result;
(void)flags;
@@ -1049,7 +1079,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
- if(conn->data != data_s)
+ if(get_transfer(httpc) != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
@@ -1073,7 +1103,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
- if(conn->data != data_s)
+ if(get_transfer(httpc) != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
@@ -1138,27 +1168,27 @@ static int error_callback(nghttp2_session *session,
size_t len,
void *userp)
{
- struct connectdata *conn = (struct connectdata *)userp;
(void)session;
- infof(conn->data, "http2 error: %.*s\n", len, msg);
+ (void)msg;
+ (void)len;
+ (void)userp;
return 0;
}
#endif
-static void populate_settings(struct connectdata *conn,
+static void populate_settings(struct Curl_easy *data,
struct http_conn *httpc)
{
nghttp2_settings_entry *iv = httpc->local_settings;
- DEBUGASSERT(conn->data);
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
- iv[0].value = Curl_multi_max_concurrent_streams(conn->data->multi);
+ iv[0].value = Curl_multi_max_concurrent_streams(data->multi);
iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
iv[1].value = HTTP2_HUGE_WINDOW_SIZE;
iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
- iv[2].value = conn->data->multi->push_cb != NULL;
+ iv[2].value = data->multi->push_cb != NULL;
httpc->local_settings_num = 3;
}
@@ -1187,6 +1217,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
if(premature) {
/* RST_STREAM */
+ set_transfer(httpc, data); /* set the transfer */
if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
http->stream_id, NGHTTP2_STREAM_CLOSED))
(void)nghttp2_session_send(httpc->h2);
@@ -1209,6 +1240,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
http->stream_id);
DEBUGASSERT(0);
}
+ set_transfer(httpc, NULL);
http->stream_id = 0;
}
}
@@ -1223,7 +1255,7 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
nghttp2_session_callbacks *callbacks;
conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
- if(conn->proto.httpc.inbuf == NULL)
+ if(!conn->proto.httpc.inbuf)
return CURLE_OUT_OF_MEMORY;
rc = nghttp2_session_callbacks_new(&callbacks);
@@ -1269,18 +1301,18 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
*/
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
- struct connectdata *conn)
+ struct Curl_easy *data)
{
CURLcode result;
ssize_t binlen;
char *base64;
size_t blen;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct SingleRequest *k = &data->req;
uint8_t *binsettings = conn->proto.httpc.binsettings;
struct http_conn *httpc = &conn->proto.httpc;
- populate_settings(conn, httpc);
+ populate_settings(data, httpc);
/* this returns number of bytes it wrote */
binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
@@ -1338,6 +1370,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf;
+ set_transfer(httpc, data); /* set the transfer */
rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
if(rv < 0) {
failf(data,
@@ -1363,7 +1396,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
}
rv = h2_session_send(data, httpc->h2);
- if(rv != 0) {
+ if(rv) {
*err = CURLE_SEND_ERROR;
return -1;
}
@@ -1377,9 +1410,10 @@ static int h2_process_pending_input(struct Curl_easy *data,
}
if(should_close_session(httpc)) {
+ struct HTTP *stream = data->req.p.http;
H2BUGF(infof(data,
"h2_process_pending_input: nothing to do in this session\n"));
- if(httpc->error_code)
+ if(stream->error)
*err = CURLE_HTTP2;
else {
/* not an error per se, but should still close the connection */
@@ -1402,9 +1436,7 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data,
if((conn->handler == &Curl_handler_http2_ssl) ||
(conn->handler == &Curl_handler_http2)) {
/* make sure this is only attempted for HTTP/2 transfers */
-
struct HTTP *stream = data->req.p.http;
-
struct http_conn *httpc = &conn->proto.httpc;
nghttp2_session *h2 = httpc->h2;
@@ -1426,13 +1458,15 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data,
H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data));
- /* re-set KEEP_SEND to make sure we are called again */
- k->keepon |= KEEP_SEND;
-
/* and attempt to send the pending frames */
rv = h2_session_send(data, h2);
- if(rv != 0)
+ if(rv)
result = CURLE_SEND_ERROR;
+
+ if(nghttp2_session_want_write(h2)) {
+ /* re-set KEEP_SEND to make sure we are called again */
+ k->keepon |= KEEP_SEND;
+ }
}
}
return result;
@@ -1460,7 +1494,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(httpc->error_code == NGHTTP2_REFUSED_STREAM) {
+ if(stream->error == NGHTTP2_REFUSED_STREAM) {
H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n",
stream->stream_id));
connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
@@ -1468,10 +1502,10 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
*err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
return -1;
}
- else if(httpc->error_code != NGHTTP2_NO_ERROR) {
+ else if(stream->error != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
- stream->stream_id, nghttp2_http2_strerror(httpc->error_code),
- httpc->error_code);
+ stream->stream_id, nghttp2_http2_strerror(stream->error),
+ stream->error);
*err = CURLE_HTTP2_STREAM;
return -1;
}
@@ -1542,6 +1576,8 @@ static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2)
{
struct HTTP *stream = data->req.p.http;
+ struct http_conn *httpc = &data->conn->proto.httpc;
+ set_transfer(httpc, data);
if((data->set.stream_weight != data->state.stream_weight) ||
(data->set.stream_depends_e != data->state.stream_depends_e) ||
(data->set.stream_depends_on != data->state.stream_depends_on) ) {
@@ -1585,6 +1621,10 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
return -1;
}
+ if(stream->closed)
+ /* closed overrides paused */
+ return http2_handle_stream_close(conn, data, stream, err);
+
/* Nullify here because we call nghttp2_session_send() and they
might refer to the old buffer. */
stream->upload_mem = NULL;
@@ -1707,6 +1747,17 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
}
if(nread == 0) {
+ if(!stream->closed) {
+ /* 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"
+ " end of the underlying stream",
+ stream->stream_id);
+ *err = CURLE_HTTP2_STREAM;
+ return -1;
+ }
+
H2BUGF(infof(data, "end of stream\n"));
*err = CURLE_OK;
return 0;
@@ -1725,7 +1776,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
nread));
}
- if(h2_process_pending_input(data, httpc, err) != 0)
+ if(h2_process_pending_input(data, httpc, err))
return -1;
}
if(stream->memlen) {
@@ -1750,7 +1801,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
return retlen;
}
if(stream->closed)
- return 0;
+ return http2_handle_stream_close(conn, data, stream, err);
*err = CURLE_AGAIN;
H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
stream->stream_id));
@@ -1925,7 +1976,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
more space. */
nheader += 1;
nva = malloc(sizeof(nghttp2_nv) * nheader);
- if(nva == NULL) {
+ if(!nva) {
*err = CURLE_OUT_OF_MEMORY;
return -1;
}
@@ -2048,7 +2099,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
}
/* :authority must come before non-pseudo header fields */
- if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
+ if(authority_idx && authority_idx != AUTHORITY_DST_IDX) {
nghttp2_nv authority = nva[authority_idx];
for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
nva[i] = nva[i - 1];
@@ -2117,10 +2168,8 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
stream_id, (void *)data);
stream->stream_id = stream_id;
- /* this does not call h2_session_send() since there can not have been any
- * priority update since the nghttp2_submit_request() call above */
- rv = nghttp2_session_send(h2);
- if(rv != 0) {
+ rv = h2_session_send(data, h2);
+ if(rv) {
H2BUGF(infof(data,
"http2_send() nghttp2_session_send error (%s)%d\n",
nghttp2_strerror(rv), rv));
@@ -2226,10 +2275,10 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
/* stream 1 is opened implicitly on upgrade */
stream->stream_id = 1;
/* queue SETTINGS frame (again) */
- rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
- httpc->binlen, NULL);
- if(rv != 0) {
- failf(data, "nghttp2_session_upgrade() failed: %s(%d)",
+ rv = nghttp2_session_upgrade2(httpc->h2, httpc->binsettings, httpc->binlen,
+ data->state.httpreq == HTTPREQ_HEAD, NULL);
+ if(rv) {
+ failf(data, "nghttp2_session_upgrade2() failed: %s(%d)",
nghttp2_strerror(rv), rv);
return CURLE_HTTP2;
}
@@ -2244,14 +2293,14 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
}
}
else {
- populate_settings(conn, httpc);
+ populate_settings(data, httpc);
/* stream ID is unknown at this point */
stream->stream_id = -1;
rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE,
httpc->local_settings,
httpc->local_settings_num);
- if(rv != 0) {
+ if(rv) {
failf(data, "nghttp2_submit_settings() failed: %s(%d)",
nghttp2_strerror(rv), rv);
return CURLE_HTTP2;
@@ -2260,7 +2309,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
HTTP2_HUGE_WINDOW_SIZE);
- if(rv != 0) {
+ if(rv) {
failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
nghttp2_strerror(rv), rv);
return CURLE_HTTP2;
@@ -2288,8 +2337,15 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
DEBUGASSERT(httpc->nread_inbuf == 0);
- if(-1 == h2_process_pending_input(data, httpc, &result))
- return CURLE_HTTP2;
+ /* Good enough to call it an end once the remaining payload is copied to the
+ * connection buffer.
+ * Some servers (e.g. nghttpx v1.43.0) may fulfill stream 1 immediately
+ * following the protocol switch other than waiting for the client-side
+ * connection preface. If h2_process_pending_input is invoked here to parse
+ * the remaining payload, stream 1 would be marked as closed too early and
+ * thus ignored in http2_recv (following 252790c53).
+ * The logic in lib/http.c and lib/transfer.c guarantees a following
+ * http2_recv would be invoked very soon. */
return CURLE_OK;
}
@@ -2299,7 +2355,8 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
/* if it isn't HTTP/2, we're done */
- if(!data->conn->proto.httpc.h2)
+ if(!(data->conn->handler->protocol & PROTO_FAMILY_HTTP) ||
+ !data->conn->proto.httpc.h2)
return CURLE_OK;
#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
else {
@@ -2423,10 +2480,10 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
/* Only call this function for a transfer that already got a HTTP/2
CURLE_HTTP2_STREAM error! */
-bool Curl_h2_http_1_1_error(struct connectdata *conn)
+bool Curl_h2_http_1_1_error(struct Curl_easy *data)
{
- struct http_conn *httpc = &conn->proto.httpc;
- return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED);
+ struct HTTP *stream = data->req.p.http;
+ return (stream->error == NGHTTP2_HTTP_1_1_REQUIRED);
}
#else /* !USE_NGHTTP2 */
diff --git a/Utilities/cmcurl/lib/http2.h b/Utilities/cmcurl/lib/http2.h
index 119e584a8..21e2c086a 100644
--- a/Utilities/cmcurl/lib/http2.h
+++ b/Utilities/cmcurl/lib/http2.h
@@ -29,7 +29,7 @@
/* value for MAX_CONCURRENT_STREAMS we use until we get an updated setting
from the peer */
-#define DEFAULT_MAX_CONCURRENT_STREAMS 13
+#define DEFAULT_MAX_CONCURRENT_STREAMS 100
/*
* Store nghttp2 version info in this buffer, Prefix with a space. Return
@@ -43,7 +43,7 @@ CURLcode Curl_http2_init(struct connectdata *conn);
void Curl_http2_init_state(struct UrlState *state);
void Curl_http2_init_userset(struct UserDefined *set);
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
- struct connectdata *conn);
+ struct Curl_easy *data);
CURLcode Curl_http2_setup(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_http2_switched(struct Curl_easy *data,
const char *ptr, size_t nread);
@@ -62,7 +62,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);
/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
-bool Curl_h2_http_1_1_error(struct connectdata *conn);
+bool Curl_h2_http_1_1_error(struct Curl_easy *data);
#else /* USE_NGHTTP2 */
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL
diff --git a/Utilities/cmcurl/lib/http_aws_sigv4.c b/Utilities/cmcurl/lib/http_aws_sigv4.c
index 8fd1c77e6..a04b46a35 100644
--- a/Utilities/cmcurl/lib/http_aws_sigv4.c
+++ b/Utilities/cmcurl/lib/http_aws_sigv4.c
@@ -99,8 +99,8 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
char *request_type = NULL;
char *credential_scope = NULL;
char *str_to_sign = NULL;
- const char *user = conn->user ? conn->user : "";
- const char *passwd = conn->passwd ? conn->passwd : "";
+ 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};
diff --git a/Utilities/cmcurl/lib/http_digest.c b/Utilities/cmcurl/lib/http_digest.c
index 596b215db..049b232e0 100644
--- a/Utilities/cmcurl/lib/http_digest.c
+++ b/Utilities/cmcurl/lib/http_digest.c
@@ -56,7 +56,7 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
digest = &data->state.digest;
}
- if(!checkprefix("Digest", header))
+ if(!checkprefix("Digest", header) || !ISSPACE(header[6]))
return CURLE_BAD_CONTENT_ENCODING;
header += strlen("Digest");
@@ -67,7 +67,6 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
}
CURLcode Curl_output_digest(struct Curl_easy *data,
- struct connectdata *conn,
bool proxy,
const unsigned char *request,
const unsigned char *uripath)
@@ -97,16 +96,16 @@ CURLcode Curl_output_digest(struct Curl_easy *data,
#else
digest = &data->state.proxydigest;
allocuserpwd = &data->state.aptr.proxyuserpwd;
- userp = conn->http_proxy.user;
- passwdp = conn->http_proxy.passwd;
+ userp = data->state.aptr.proxyuser;
+ passwdp = data->state.aptr.proxypasswd;
authp = &data->state.authproxy;
#endif
}
else {
digest = &data->state.digest;
allocuserpwd = &data->state.aptr.userpwd;
- userp = conn->user;
- passwdp = conn->passwd;
+ userp = data->state.aptr.user;
+ passwdp = data->state.aptr.passwd;
authp = &data->state.authhost;
}
diff --git a/Utilities/cmcurl/lib/http_digest.h b/Utilities/cmcurl/lib/http_digest.h
index 106caa7c4..89438d1a1 100644
--- a/Utilities/cmcurl/lib/http_digest.h
+++ b/Utilities/cmcurl/lib/http_digest.h
@@ -31,7 +31,6 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
/* this is for creating digest header output */
CURLcode Curl_output_digest(struct Curl_easy *data,
- struct connectdata *conn,
bool proxy,
const unsigned char *request,
const unsigned char *uripath);
diff --git a/Utilities/cmcurl/lib/http_negotiate.c b/Utilities/cmcurl/lib/http_negotiate.c
index d759748f2..68cce1bbb 100644
--- a/Utilities/cmcurl/lib/http_negotiate.c
+++ b/Utilities/cmcurl/lib/http_negotiate.c
@@ -179,7 +179,7 @@ CURLcode Curl_output_negotiate(struct Curl_easy *data,
free(base64);
- if(userp == NULL) {
+ if(!userp) {
return CURLE_OUT_OF_MEMORY;
}
diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index 6cb829edf..e200fdb1d 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -39,6 +39,7 @@
#include "http_ntlm.h"
#include "curl_ntlm_core.h"
#include "curl_ntlm_wb.h"
+#include "curl_base64.h"
#include "vauth/vauth.h"
#include "url.h"
@@ -80,7 +81,18 @@ CURLcode Curl_input_ntlm(struct Curl_easy *data,
header++;
if(*header) {
- result = Curl_auth_decode_ntlm_type2_message(data, header, ntlm);
+ unsigned char *hdr;
+ size_t hdrlen;
+
+ result = Curl_base64_decode(header, &hdr, &hdrlen);
+ if(!result) {
+ struct bufref hdrbuf;
+
+ Curl_bufref_init(&hdrbuf);
+ Curl_bufref_set(&hdrbuf, hdr, hdrlen, curl_free);
+ result = Curl_auth_decode_ntlm_type2_message(data, &hdrbuf, ntlm);
+ Curl_bufref_free(&hdrbuf);
+ }
if(result)
return result;
@@ -116,7 +128,8 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
{
char *base64 = NULL;
size_t len = 0;
- CURLcode result;
+ CURLcode result = CURLE_OK;
+ struct bufref ntlmmsg;
/* point to the address of the pointer that holds the string to send to the
server, which is for a plain host or for a HTTP proxy */
@@ -140,10 +153,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
if(proxy) {
#ifndef CURL_DISABLE_PROXY
allocuserpwd = &data->state.aptr.proxyuserpwd;
- userp = conn->http_proxy.user;
- passwdp = conn->http_proxy.passwd;
+ userp = data->state.aptr.proxyuser;
+ passwdp = data->state.aptr.proxypasswd;
service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
- data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
+ data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
hostname = conn->http_proxy.host.name;
ntlm = &conn->proxyntlm;
state = &conn->proxy_ntlm_state;
@@ -154,10 +167,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
}
else {
allocuserpwd = &data->state.aptr.userpwd;
- userp = conn->user;
- passwdp = conn->passwd;
+ userp = data->state.aptr.user;
+ passwdp = data->state.aptr.passwd;
service = data->set.str[STRING_SERVICE_NAME] ?
- data->set.str[STRING_SERVICE_NAME] : "HTTP";
+ data->set.str[STRING_SERVICE_NAME] : "HTTP";
hostname = conn->host.name;
ntlm = &conn->ntlm;
state = &conn->http_ntlm_state;
@@ -173,10 +186,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
passwdp = "";
#ifdef USE_WINDOWS_SSPI
- if(s_hSecDll == NULL) {
+ if(!s_hSecDll) {
/* not thread safe and leaks - use curl_global_init() to avoid */
CURLcode err = Curl_sspi_global_init();
- if(s_hSecDll == NULL)
+ if(!s_hSecDll)
return err;
}
#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
@@ -184,50 +197,52 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
#endif
#endif
+ Curl_bufref_init(&ntlmmsg);
switch(*state) {
case NTLMSTATE_TYPE1:
default: /* for the weird cases we (re)start here */
/* Create a type-1 message */
result = Curl_auth_create_ntlm_type1_message(data, userp, passwdp,
service, hostname,
- ntlm, &base64,
- &len);
- if(result)
- return result;
-
- if(base64) {
- free(*allocuserpwd);
- *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
- proxy ? "Proxy-" : "",
- base64);
- free(base64);
- if(!*allocuserpwd)
- return CURLE_OUT_OF_MEMORY;
-
- DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
+ ntlm, &ntlmmsg);
+ if(!result) {
+ DEBUGASSERT(Curl_bufref_len(&ntlmmsg) != 0);
+ result = Curl_base64_encode(data,
+ (const char *) Curl_bufref_ptr(&ntlmmsg),
+ Curl_bufref_len(&ntlmmsg), &base64, &len);
+ if(!result) {
+ free(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
+ proxy ? "Proxy-" : "",
+ base64);
+ free(base64);
+ if(!*allocuserpwd)
+ result = CURLE_OUT_OF_MEMORY;
+ }
}
break;
case NTLMSTATE_TYPE2:
/* We already received the type-2 message, create a type-3 message */
result = Curl_auth_create_ntlm_type3_message(data, userp, passwdp,
- ntlm, &base64, &len);
- if(result)
- return result;
-
- if(base64) {
- free(*allocuserpwd);
- *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
- proxy ? "Proxy-" : "",
- base64);
- free(base64);
- if(!*allocuserpwd)
- return CURLE_OUT_OF_MEMORY;
-
- DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
-
- *state = NTLMSTATE_TYPE3; /* we send a type-3 */
- authp->done = TRUE;
+ ntlm, &ntlmmsg);
+ if(!result && Curl_bufref_len(&ntlmmsg)) {
+ result = Curl_base64_encode(data,
+ (const char *) Curl_bufref_ptr(&ntlmmsg),
+ Curl_bufref_len(&ntlmmsg), &base64, &len);
+ if(!result) {
+ free(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
+ proxy ? "Proxy-" : "",
+ base64);
+ free(base64);
+ if(!*allocuserpwd)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ *state = NTLMSTATE_TYPE3; /* we send a type-3 */
+ authp->done = TRUE;
+ }
+ }
}
break;
@@ -241,8 +256,9 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
authp->done = TRUE;
break;
}
+ Curl_bufref_free(&ntlmmsg);
- return CURLE_OK;
+ return result;
}
void Curl_http_auth_cleanup_ntlm(struct connectdata *conn)
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index a03a27fdc..a3a62c1ca 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -39,6 +39,8 @@
#include "connect.h"
#include "curlx.h"
#include "vtls/vtls.h"
+#include "transfer.h"
+#include "multiif.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -88,29 +90,12 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
#ifndef CURL_DISABLE_PROXY
/* for [protocol] tunneled through HTTP proxy */
- struct HTTP http_proxy;
- void *prot_save;
const char *hostname;
int remote_port;
CURLcode result;
- /* BLOCKING */
/* We want "seamless" operations through HTTP proxy tunnel */
- /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
- * member conn->proto.http; we want [protocol] through HTTP and we have
- * to change the member temporarily for connecting to the HTTP
- * proxy. After Curl_proxyCONNECT we have to set back the member to the
- * original pointer
- *
- * This function might be called several times in the multi interface case
- * if the proxy's CONNECT response is not instant.
- */
- prot_save = data->req.p.http;
- memset(&http_proxy, 0, sizeof(http_proxy));
- data->req.p.http = &http_proxy;
- connkeep(conn, "HTTP proxy CONNECT");
-
/* for the secondary socket (FTP), use the "connect to host"
* but ignore the "connect to port" (use the secondary port)
*/
@@ -128,8 +113,8 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
remote_port = conn->conn_to_port;
else
remote_port = conn->remote_port;
+
result = Curl_proxyCONNECT(data, sockindex, hostname, remote_port);
- data->req.p.http = prot_save;
if(CURLE_OK != result)
return result;
Curl_safefree(data->state.aptr.proxyuserpwd);
@@ -153,18 +138,53 @@ bool Curl_connect_ongoing(struct connectdata *conn)
(conn->connect_state->tunnel_state != TUNNEL_COMPLETE);
}
+/* when we've sent a CONNECT to a proxy, we should rather either wait for the
+ socket to become readable to be able to get the response headers or if
+ we're still sending the request, wait for write. */
+int Curl_connect_getsock(struct connectdata *conn)
+{
+ struct HTTP *http;
+ DEBUGASSERT(conn);
+ DEBUGASSERT(conn->connect_state);
+ http = &conn->connect_state->http_proxy;
+
+ if(http->sending)
+ return GETSOCK_WRITESOCK(0);
+
+ return GETSOCK_READSOCK(0);
+}
+
static CURLcode connect_init(struct Curl_easy *data, bool reinit)
{
struct http_connect_state *s;
struct connectdata *conn = data->conn;
if(!reinit) {
+ CURLcode result;
DEBUGASSERT(!conn->connect_state);
+ /* we might need the upload buffer for streaming a partial request */
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
+
s = calloc(1, sizeof(struct http_connect_state));
if(!s)
return CURLE_OUT_OF_MEMORY;
infof(data, "allocate connect buffer!\n");
conn->connect_state = s;
Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
+
+ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
+ * member conn->proto.http; we want [protocol] through HTTP and we have
+ * to change the member temporarily for connecting to the HTTP
+ * proxy. After Curl_proxyCONNECT we have to set back the member to the
+ * original pointer
+ *
+ * This function might be called several times in the multi interface case
+ * if the proxy's CONNECT response is not instant.
+ */
+ s->prot_save = data->req.p.http;
+ data->req.p.http = &s->http_proxy;
+ connkeep(conn, "HTTP proxy CONNECT");
}
else {
DEBUGASSERT(conn->connect_state);
@@ -184,6 +204,10 @@ static void connect_done(struct Curl_easy *data)
struct http_connect_state *s = conn->connect_state;
s->tunnel_state = TUNNEL_COMPLETE;
Curl_dyn_free(&s->rcvbuf);
+ Curl_dyn_free(&s->req);
+
+ /* retore the protocol pointer */
+ data->req.p.http = s->prot_save;
infof(data, "CONNECT phase completed!\n");
}
@@ -231,6 +255,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
struct connectdata *conn = data->conn;
curl_socket_t tunnelsocket = conn->sock[sockindex];
struct http_connect_state *s = conn->connect_state;
+ struct HTTP *http = data->req.p.http;
char *linep;
size_t perline;
@@ -246,7 +271,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
timediff_t check;
if(TUNNEL_INIT == s->tunnel_state) {
/* BEGIN CONNECT PHASE */
- struct dynbuf req;
+ struct dynbuf *req = &s->req;
char *hostheader = NULL;
char *host = NULL;
@@ -259,8 +284,8 @@ static CURLcode CONNECT(struct Curl_easy *data,
free(data->req.newurl);
data->req.newurl = NULL;
- /* initialize a dynamic send-buffer */
- Curl_dyn_init(&req, DYN_HTTP_REQUEST);
+ /* initialize send-buffer */
+ Curl_dyn_init(req, DYN_HTTP_REQUEST);
result = CONNECT_host(data, conn,
hostname, remote_port, &hostheader, &host);
@@ -285,7 +310,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
useragent = data->state.aptr.uagent;
result =
- Curl_dyn_addf(&req,
+ Curl_dyn_addf(req,
"CONNECT %s HTTP/%s\r\n"
"%s" /* Host: */
"%s" /* Proxy-Authorization */
@@ -300,16 +325,15 @@ static CURLcode CONNECT(struct Curl_easy *data,
proxyconn);
if(!result)
- result = Curl_add_custom_headers(data, TRUE, &req);
+ result = Curl_add_custom_headers(data, TRUE, req);
if(!result)
/* CRLF terminate the request */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(req, "\r\n");
if(!result) {
/* Send the connect request to the proxy */
- /* BLOCKING */
- result = Curl_buffer_send(&req, data, &data->info.request_size, 0,
+ result = Curl_buffer_send(req, data, &data->info.request_size, 0,
sockindex);
}
if(result)
@@ -317,7 +341,6 @@ static CURLcode CONNECT(struct Curl_easy *data,
}
free(host);
free(hostheader);
- Curl_dyn_free(&req);
if(result)
return result;
@@ -330,12 +353,42 @@ static CURLcode CONNECT(struct Curl_easy *data,
return CURLE_OPERATION_TIMEDOUT;
}
- if(!Curl_conn_data_pending(conn, sockindex))
+ if(!Curl_conn_data_pending(conn, sockindex) && !http->sending)
/* return so we'll be called again polling-style */
return CURLE_OK;
/* at this point, the tunnel_connecting phase is over. */
+ if(http->sending == HTTPSEND_REQUEST) {
+ if(!s->nsend) {
+ size_t fillcount;
+ k->upload_fromhere = data->state.ulbuf;
+ result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
+ &fillcount);
+ if(result)
+ return result;
+ s->nsend = fillcount;
+ }
+ if(s->nsend) {
+ ssize_t bytes_written;
+ /* write to socket (send away data) */
+ result = Curl_write(data,
+ conn->writesockfd, /* socket to send to */
+ k->upload_fromhere, /* buffer pointer */
+ s->nsend, /* buffer size */
+ &bytes_written); /* actually sent */
+
+ if(!result)
+ /* send to debug callback! */
+ result = Curl_debug(data, CURLINFO_HEADER_OUT,
+ k->upload_fromhere, bytes_written);
+
+ s->nsend -= bytes_written;
+ k->upload_fromhere += bytes_written;
+ return result;
+ }
+ /* if nothing left to send, continue */
+ }
{ /* READING RESPONSE PHASE */
int error = SELECT_OK;
@@ -358,7 +411,8 @@ static CURLcode CONNECT(struct Curl_easy *data,
break;
}
else if(gotbytes <= 0) {
- if(data->set.proxyauth && data->state.authproxy.avail) {
+ if(data->set.proxyauth && data->state.authproxy.avail &&
+ data->state.aptr.proxyuserpwd) {
/* proxy auth was requested and there was proxy auth available,
then deem this as "mere" proxy disconnect */
conn->bits.proxy_connect_closed = TRUE;
@@ -759,7 +813,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
(HYPERE_OK != hyper_request_set_version(req,
HYPER_HTTP_VERSION_1_0))) {
- failf(data, "error settting HTTP version");
+ failf(data, "error setting HTTP version");
goto error;
}
diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h
index a78db0d04..f5a4cb07c 100644
--- a/Utilities/cmcurl/lib/http_proxy.h
+++ b/Utilities/cmcurl/lib/http_proxy.h
@@ -38,15 +38,39 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex);
bool Curl_connect_complete(struct connectdata *conn);
bool Curl_connect_ongoing(struct connectdata *conn);
+int Curl_connect_getsock(struct connectdata *conn);
#else
#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
#define Curl_proxy_connect(x,y) CURLE_OK
#define Curl_connect_complete(x) CURLE_OK
#define Curl_connect_ongoing(x) FALSE
+#define Curl_connect_getsock(x) 0
#endif
void Curl_connect_free(struct Curl_easy *data);
void Curl_connect_done(struct Curl_easy *data);
+/* struct for HTTP CONNECT state data */
+struct http_connect_state {
+ struct HTTP http_proxy;
+ struct HTTP *prot_save;
+ struct dynbuf rcvbuf;
+ struct dynbuf req;
+ size_t nsend;
+ enum keeponval {
+ KEEPON_DONE,
+ KEEPON_CONNECT,
+ KEEPON_IGNORE
+ } keepon;
+ curl_off_t cl; /* size of content to read and ignore */
+ enum {
+ TUNNEL_INIT, /* init/default/no tunnel state */
+ TUNNEL_CONNECT, /* CONNECT has been sent off */
+ TUNNEL_COMPLETE /* CONNECT response received completely */
+ } tunnel_state;
+ BIT(chunked_encoding);
+ BIT(close_connection);
+};
+
#endif /* HEADER_CURL_HTTP_PROXY_H */
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index 2d8069921..d85bcc391 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_imap = {
imap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_IMAP, /* defport */
CURLPROTO_IMAP, /* protocol */
CURLPROTO_IMAP, /* family */
@@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_imaps = {
imap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_IMAPS, /* defport */
CURLPROTO_IMAPS, /* protocol */
CURLPROTO_IMAP, /* family */
@@ -919,7 +921,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
/* Do we have a SASL based authentication mechanism? */
else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) {
size_t llen;
- unsigned int mechbit;
+ unsigned short mechbit;
line += 5;
wordlen -= 5;
@@ -1519,7 +1521,7 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
Curl_safefree(imap->custom_params);
/* Clear the transfer mode for the next request */
- imap->transfer = FTPTRANSFER_BODY;
+ imap->transfer = PPTRANSFER_BODY;
return result;
}
@@ -1545,7 +1547,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
if(data->set.opt_no_body) {
/* Requested no body means no transfer */
- imap->transfer = FTPTRANSFER_INFO;
+ imap->transfer = PPTRANSFER_INFO;
}
*dophase_done = FALSE; /* not done yet */
@@ -1667,7 +1669,7 @@ static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected)
(void)connected;
- if(imap->transfer != FTPTRANSFER_BODY)
+ if(imap->transfer != PPTRANSFER_BODY)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
diff --git a/Utilities/cmcurl/lib/inet_ntop.c b/Utilities/cmcurl/lib/inet_ntop.c
index 9a5af7f42..4c3e9e4da 100644
--- a/Utilities/cmcurl/lib/inet_ntop.c
+++ b/Utilities/cmcurl/lib/inet_ntop.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1996-2019 Internet Software Consortium.
+ * Copyright (C) 1996-2021 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
@@ -134,7 +134,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
/* Are we following an initial run of 0x00s or any real hex?
*/
- if(i != 0)
+ if(i)
*tp++ = ':';
/* Is this address an encapsulated IPv4?
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index 46116ce59..c8c4b6601 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -160,16 +160,6 @@ krb5_decode(void *app_data, void *buf, int len,
}
static int
-krb5_overhead(void *app_data, int level, int len)
-{
- /* no arguments are used */
- (void)app_data;
- (void)level;
- (void)len;
- return 0;
-}
-
-static int
krb5_encode(void *app_data, const void *from, int length, int level, void **to)
{
gss_ctx_id_t *context = app_data;
@@ -305,7 +295,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
break;
}
- if(output_buffer.length != 0) {
+ if(output_buffer.length) {
char *cmd;
result = Curl_base64_encode(data, (char *)output_buffer.value,
@@ -392,7 +382,7 @@ static struct Curl_sec_client_mech Curl_krb5_client_mech = {
krb5_auth,
krb5_end,
krb5_check_prot,
- krb5_overhead,
+
krb5_encode,
krb5_decode
};
@@ -412,7 +402,7 @@ name_to_level(const char *name)
{
int i;
for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++)
- if(checkprefix(name, level_names[i].name))
+ if(curl_strequal(name, level_names[i].name))
return level_names[i].level;
return PROT_NONE;
}
@@ -657,8 +647,6 @@ static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn,
{
ssize_t tx = 0, len = conn->buffer_size;
- len -= conn->mech->overhead(conn->app_data, conn->data_prot,
- curlx_sztosi(len));
if(len <= 0)
len = length;
while(length) {
@@ -760,7 +748,7 @@ static int sec_set_protection_level(struct Curl_easy *data)
if(level) {
char *pbsz;
- static unsigned int buffer_size = 1 << 20; /* 1048576 */
+ unsigned int buffer_size = 1 << 20; /* 1048576 */
code = ftp_send_command(data, "PBSZ %u", buffer_size);
if(code < 0)
@@ -817,7 +805,7 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn)
const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech;
tmp_allocation = realloc(conn->app_data, mech->size);
- if(tmp_allocation == NULL) {
+ if(!tmp_allocation) {
failf(data, "Failed realloc of size %zu", mech->size);
mech = NULL;
return CURLE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 307ebebaf..ed1642302 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -149,6 +149,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
CURLPROTO_LDAP, /* family */
@@ -176,6 +177,7 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_LDAPS, /* defport */
CURLPROTO_LDAPS, /* protocol */
CURLPROTO_LDAP, /* family */
@@ -296,14 +298,14 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
*done = TRUE; /* unconditionally */
infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
- infof(data, "LDAP local: %s\n", data->change.url);
+ infof(data, "LDAP local: %s\n", data->state.url);
#ifdef HAVE_LDAP_URL_PARSE
- rc = ldap_url_parse(data->change.url, &ludp);
+ rc = ldap_url_parse(data->state.url, &ludp);
#else
rc = _ldap_url_parse(data, conn, &ludp);
#endif
- if(rc != 0) {
+ if(rc) {
failf(data, "LDAP local: %s", ldap_err2string(rc));
result = CURLE_LDAP_INVALID_URL;
goto quit;
@@ -387,7 +389,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
server = ldapssl_init(host, (int)conn->port, 1);
- if(server == NULL) {
+ if(!server) {
failf(data, "LDAP local: Cannot connect to %s:%ld",
conn->host.dispname, conn->port);
result = CURLE_COULDNT_CONNECT;
@@ -428,7 +430,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
server = ldap_init(host, (int)conn->port);
- if(server == NULL) {
+ if(!server) {
failf(data, "LDAP local: Cannot connect to %s:%ld",
conn->host.dispname, conn->port);
result = CURLE_COULDNT_CONNECT;
@@ -464,7 +466,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
}
else {
server = ldap_init(host, (int)conn->port);
- if(server == NULL) {
+ if(!server) {
failf(data, "LDAP local: Cannot connect to %s:%ld",
conn->host.dispname, conn->port);
result = CURLE_COULDNT_CONNECT;
@@ -477,7 +479,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
#else
rc = ldap_simple_bind_s(server, user, passwd);
#endif
- if(!ldap_ssl && rc != 0) {
+ if(!ldap_ssl && rc) {
ldap_proto = LDAP_VERSION2;
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
#ifdef USE_WIN32_LDAP
@@ -486,7 +488,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
rc = ldap_simple_bind_s(server, user, passwd);
#endif
}
- if(rc != 0) {
+ if(rc) {
#ifdef USE_WIN32_LDAP
failf(data, "LDAP local: bind via ldap_win_bind %s",
ldap_err2string(rc));
@@ -501,7 +503,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg);
- if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) {
+ if(rc && rc != LDAP_SIZELIMIT_EXCEEDED) {
failf(data, "LDAP remote: %s", ldap_err2string(rc));
result = CURLE_LDAP_SEARCH_FAILED;
goto quit;
@@ -581,7 +583,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
result = CURLE_OUT_OF_MEMORY;
goto quit;
- }
+ }
#else
char *attr = attribute;
#endif
@@ -875,7 +877,7 @@ static int _ldap_url_parse2(struct Curl_easy *data,
ludp->lud_dn = curlx_convert_UTF8_to_tchar(unescaped);
/* Free the unescaped string as we are done with it */
- curlx_unicodefree(unescaped);
+ free(unescaped);
if(!ludp->lud_dn) {
rc = LDAP_NO_MEMORY;
@@ -943,7 +945,7 @@ static int _ldap_url_parse2(struct Curl_easy *data,
ludp->lud_attrs[i] = curlx_convert_UTF8_to_tchar(unescaped);
/* Free the unescaped string as we are done with it */
- curlx_unicodefree(unescaped);
+ free(unescaped);
if(!ludp->lud_attrs[i]) {
free(attributes);
@@ -1010,7 +1012,7 @@ static int _ldap_url_parse2(struct Curl_easy *data,
ludp->lud_filter = curlx_convert_UTF8_to_tchar(unescaped);
/* Free the unescaped string as we are done with it */
- curlx_unicodefree(unescaped);
+ free(unescaped);
if(!ludp->lud_filter) {
rc = LDAP_NO_MEMORY;
@@ -1061,13 +1063,23 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp)
if(!ludp)
return;
+#if defined(USE_WIN32_LDAP)
+ curlx_unicodefree(ludp->lud_dn);
+ curlx_unicodefree(ludp->lud_filter);
+#else
free(ludp->lud_dn);
free(ludp->lud_filter);
+#endif
if(ludp->lud_attrs) {
size_t i;
- for(i = 0; i < ludp->lud_attrs_dups; i++)
+ for(i = 0; i < ludp->lud_attrs_dups; i++) {
+#if defined(USE_WIN32_LDAP)
+ curlx_unicodefree(ludp->lud_attrs[i]);
+#else
free(ludp->lud_attrs[i]);
+#endif
+ }
free(ludp->lud_attrs);
}
diff --git a/Utilities/cmcurl/lib/llist.c b/Utilities/cmcurl/lib/llist.c
index 17a7be166..e0ec7393d 100644
--- a/Utilities/cmcurl/lib/llist.c
+++ b/Utilities/cmcurl/lib/llist.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -94,13 +94,13 @@ Curl_llist_remove(struct Curl_llist *list, struct Curl_llist_element *e,
void *user)
{
void *ptr;
- if(e == NULL || list->size == 0)
+ if(!e || list->size == 0)
return;
if(e == list->head) {
list->head = e->next;
- if(list->head == NULL)
+ if(!list->head)
list->tail = NULL;
else
e->next->prev = NULL;
diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c
index 8ae6ac3fa..c651ddf66 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -44,7 +44,7 @@
#endif
#endif /* USE_MBEDTLS */
-#if defined(USE_GNUTLS_NETTLE)
+#if defined(USE_GNUTLS)
#include <nettle/md4.h>
@@ -70,33 +70,6 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
md4_digest(ctx, MD4_DIGEST_SIZE, result);
}
-#elif defined(USE_GNUTLS)
-
-#include <gcrypt.h>
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
-typedef gcry_md_hd_t MD4_CTX;
-
-static void MD4_Init(MD4_CTX *ctx)
-{
- gcry_md_open(ctx, GCRY_MD_MD4, 0);
-}
-
-static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
-{
- gcry_md_write(*ctx, data, size);
-}
-
-static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
-{
- memcpy(result, gcry_md_read(*ctx, 0), MD4_DIGEST_LENGTH);
- gcry_md_close(*ctx);
-}
-
#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
/* When OpenSSL is available we use the MD4-functions from OpenSSL */
#include <openssl/md4.h>
@@ -201,7 +174,7 @@ static void MD4_Init(MD4_CTX *ctx)
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
{
- if(ctx->data == NULL) {
+ if(!ctx->data) {
ctx->data = malloc(size);
if(ctx->data != NULL) {
memcpy(ctx->data, data, size);
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index 513ffb2fb..7a24fd8cf 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -38,7 +38,7 @@
#endif
#endif /* USE_MBEDTLS */
-#if defined(USE_GNUTLS_NETTLE)
+#if defined(USE_GNUTLS)
#include <nettle/md5.h>
#include "curl_memory.h"
@@ -64,33 +64,6 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
md5_digest(ctx, 16, digest);
}
-#elif defined(USE_GNUTLS)
-
-#include <gcrypt.h>
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
-
-typedef gcry_md_hd_t MD5_CTX;
-
-static void MD5_Init(MD5_CTX *ctx)
-{
- gcry_md_open(ctx, GCRY_MD_MD5, 0);
-}
-
-static void MD5_Update(MD5_CTX *ctx,
- const unsigned char *input,
- unsigned int inputLen)
-{
- gcry_md_write(*ctx, input, inputLen);
-}
-
-static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
-{
- memcpy(digest, gcry_md_read(*ctx, 0), 16);
- gcry_md_close(*ctx);
-}
-
#elif defined(USE_OPENSSL) && !defined(USE_AMISSL)
/* When OpenSSL is available we use the MD5-function from OpenSSL */
#include <openssl/md5.h>
diff --git a/Utilities/cmcurl/lib/memdebug.c b/Utilities/cmcurl/lib/memdebug.c
index 881ee85c3..050c5d4b2 100644
--- a/Utilities/cmcurl/lib/memdebug.c
+++ b/Utilities/cmcurl/lib/memdebug.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -55,9 +55,24 @@ struct memdebug {
*/
FILE *curl_dbg_logfile = NULL;
+static bool registered_cleanup = FALSE; /* atexit registered cleanup */
static bool memlimit = FALSE; /* enable memory limit */
static long memsize = 0; /* set number of mallocs allowed */
+/* LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected
+ on exit so the logfile must be closed explicitly or data could be lost.
+ Though _exit() does not call atexit handlers such as this, LSAN's call to
+ _exit() comes after the atexit handlers are called. curl/curl#6620 */
+static void curl_dbg_cleanup(void)
+{
+ if(curl_dbg_logfile &&
+ curl_dbg_logfile != stderr &&
+ curl_dbg_logfile != stdout) {
+ fclose(curl_dbg_logfile);
+ }
+ curl_dbg_logfile = NULL;
+}
+
/* this sets the log file name */
void curl_dbg_memdebug(const char *logname)
{
@@ -72,6 +87,8 @@ void curl_dbg_memdebug(const char *logname)
setbuf(curl_dbg_logfile, (char *)NULL);
#endif
}
+ if(!registered_cleanup)
+ registered_cleanup = !atexit(curl_dbg_cleanup);
}
/* This function sets the number of malloc() calls that should return
@@ -91,15 +108,13 @@ static bool countcheck(const char *func, int line, const char *source)
should not be made */
if(memlimit && source) {
if(!memsize) {
- if(source) {
- /* log to file */
- curl_dbg_log("LIMIT %s:%d %s reached memlimit\n",
- source, line, func);
- /* log to stderr also */
- fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
- source, line, func);
- fflush(curl_dbg_logfile); /* because it might crash now */
- }
+ /* log to file */
+ curl_dbg_log("LIMIT %s:%d %s reached memlimit\n",
+ source, line, func);
+ /* log to stderr also */
+ fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
+ source, line, func);
+ fflush(curl_dbg_logfile); /* because it might crash now */
errno = ENOMEM;
return TRUE; /* RETURN ERROR! */
}
diff --git a/Utilities/cmcurl/lib/mime.c b/Utilities/cmcurl/lib/mime.c
index abadcb02c..0bf1b46a4 100644
--- a/Utilities/cmcurl/lib/mime.c
+++ b/Utilities/cmcurl/lib/mime.c
@@ -152,14 +152,14 @@ curl_off_t VmsRealFileSize(const char *name,
FILE * file;
file = fopen(name, FOPEN_READTEXT); /* VMS */
- if(file == NULL)
+ if(!file)
return 0;
count = 0;
ret_stat = 1;
while(ret_stat > 0) {
ret_stat = fread(buffer, 1, sizeof(buffer), file);
- if(ret_stat != 0)
+ if(ret_stat)
count += ret_stat;
}
fclose(file);
diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c
index c681248de..529202686 100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1999 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1999 - 2021, 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
@@ -815,7 +815,7 @@ static int dprintf_formatf(
size_t len;
str = (char *) p->data.str;
- if(str == NULL) {
+ if(!str) {
/* Write null[] if there's space. */
if(prec == -1 || prec >= (long) sizeof(null) - 1) {
str = null;
diff --git a/Utilities/cmcurl/lib/mqtt.c b/Utilities/cmcurl/lib/mqtt.c
index 2134409cd..d88fa737d 100644
--- a/Utilities/cmcurl/lib/mqtt.c
+++ b/Utilities/cmcurl/lib/mqtt.c
@@ -86,6 +86,7 @@ const struct Curl_handler Curl_handler_mqtt = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_MQTT, /* defport */
CURLPROTO_MQTT, /* protocol */
CURLPROTO_MQTT, /* family */
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 85707a1af..1b3e261c6 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -83,19 +83,19 @@ static void process_pending_handles(struct Curl_multi *multi);
#ifdef DEBUGBUILD
static const char * const statename[]={
"INIT",
- "CONNECT_PEND",
+ "PENDING",
"CONNECT",
- "WAITRESOLVE",
- "WAITCONNECT",
- "WAITPROXYCONNECT",
- "SENDPROTOCONNECT",
+ "RESOLVING",
+ "CONNECTING",
+ "TUNNELING",
"PROTOCONNECT",
+ "PROTOCONNECTING",
"DO",
"DOING",
- "DO_MORE",
- "DO_DONE",
- "PERFORM",
- "TOOFAST",
+ "DOING_MORE",
+ "DID",
+ "PERFORMING",
+ "RATELIMITING",
"DONE",
"COMPLETED",
"MSGSENT",
@@ -105,8 +105,8 @@ static const char * const statename[]={
/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct Curl_easy *data);
-/* called when the PERFORM state starts */
-static void init_perform(struct Curl_easy *data)
+/* called in DID state, before PERFORMING state */
+static void before_perform(struct Curl_easy *data)
{
data->req.chunk = FALSE;
Curl_pgrsTime(data, TIMER_PRETRANSFER);
@@ -130,21 +130,21 @@ static void mstate(struct Curl_easy *data, CURLMstate state
)
{
CURLMstate oldstate = data->mstate;
- static const init_multistate_func finit[CURLM_STATE_LAST] = {
+ static const init_multistate_func finit[MSTATE_LAST] = {
NULL, /* INIT */
- NULL, /* CONNECT_PEND */
+ NULL, /* PENDING */
Curl_init_CONNECT, /* CONNECT */
- NULL, /* WAITRESOLVE */
- NULL, /* WAITCONNECT */
- NULL, /* WAITPROXYCONNECT */
- NULL, /* SENDPROTOCONNECT */
+ NULL, /* RESOLVING */
+ NULL, /* CONNECTING */
+ NULL, /* TUNNELING */
NULL, /* PROTOCONNECT */
+ NULL, /* PROTOCONNECTING */
Curl_connect_free, /* DO */
NULL, /* DOING */
- NULL, /* DO_MORE */
- NULL, /* DO_DONE */
- init_perform, /* PERFORM */
- NULL, /* TOOFAST */
+ NULL, /* DOING_MORE */
+ before_perform, /* DID */
+ NULL, /* PERFORMING */
+ NULL, /* RATELIMITING */
NULL, /* DONE */
init_completed, /* COMPLETED */
NULL /* MSGSENT */
@@ -161,8 +161,8 @@ static void mstate(struct Curl_easy *data, CURLMstate state
data->mstate = state;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- if(data->mstate >= CURLM_STATE_CONNECT_PEND &&
- data->mstate < CURLM_STATE_COMPLETED) {
+ if(data->mstate >= MSTATE_PENDING &&
+ data->mstate < MSTATE_COMPLETED) {
long connection_id = -5000;
if(data->conn)
@@ -175,7 +175,7 @@ static void mstate(struct Curl_easy *data, CURLMstate state
}
#endif
- if(state == CURLM_STATE_COMPLETED) {
+ if(state == MSTATE_COMPLETED) {
/* changing to COMPLETED means there's one less easy handle 'alive' */
DEBUGASSERT(data->multi->num_alive > 0);
data->multi->num_alive--;
@@ -381,6 +381,11 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
multi->max_concurrent_streams = 100;
multi->ipv6_works = Curl_ipv6works(NULL);
+#ifdef USE_WINSOCK
+ multi->wsa_event = WSACreateEvent();
+ if(multi->wsa_event == WSA_INVALID_EVENT)
+ goto error;
+#else
#ifdef ENABLE_WAKEUP
if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
@@ -394,6 +399,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
multi->wakeup_pair[1] = CURL_SOCKET_BAD;
}
#endif
+#endif
return multi;
@@ -447,7 +453,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
data->set.errorbuffer[0] = 0;
/* set the easy handle */
- multistate(data, CURLM_STATE_INIT);
+ multistate(data, MSTATE_INIT);
/* for multi interface connections, we share DNS cache automatically if the
easy handle's one is currently not set. */
@@ -562,8 +568,6 @@ static CURLcode multi_done(struct Curl_easy *data,
/* Stop if multi_done() has already been called */
return CURLE_OK;
- conn->data = data; /* ensure the connection uses this transfer now */
-
/* Stop the resolver and free its own resources (but not dns_entry yet). */
Curl_resolver_kill(data);
@@ -604,16 +608,13 @@ static CURLcode multi_done(struct Curl_easy *data,
Curl_detach_connnection(data);
if(CONN_INUSE(conn)) {
/* Stop if still used. */
- /* conn->data must not remain pointing to this transfer since it is going
- away! Find another to own it! */
- conn->data = conn->easyq.head->ptr;
CONNCACHE_UNLOCK(data);
DEBUGF(infof(data, "Connection still in use %zu, "
"no more multi_done now!\n",
conn->easyq.size));
return CURLE_OK;
}
- conn->data = NULL; /* the connection now has no owner */
+
data->state.done = TRUE; /* called just now! */
if(conn->dns_entry) {
@@ -718,7 +719,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
{
struct Curl_easy *easy = data;
bool premature;
- bool easy_owns_conn;
struct Curl_llist_element *e;
/* First, make some basic checks that the CURLM handle is a good handle */
@@ -740,9 +740,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
- premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
- easy_owns_conn = (data->conn && (data->conn->data == easy)) ?
- TRUE : FALSE;
+ premature = (data->mstate < MSTATE_COMPLETED) ? TRUE : FALSE;
/* If the 'state' is not INIT or COMPLETED, we might need to do something
nice to put the easy_handle in a good known state when this returns. */
@@ -753,28 +751,20 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
}
if(data->conn &&
- data->mstate > CURLM_STATE_DO &&
- data->mstate < CURLM_STATE_COMPLETED) {
+ data->mstate > MSTATE_DO &&
+ data->mstate < MSTATE_COMPLETED) {
/* Set connection owner so that the DONE function closes it. We can
safely do this here since connection is killed. */
- data->conn->data = easy;
streamclose(data->conn, "Removed with partial response");
- easy_owns_conn = TRUE;
}
if(data->conn) {
+ /* multi_done() clears the association between the easy handle and the
+ connection.
- /* we must call multi_done() here (if we still own the connection) so that
- we don't leave a half-baked one around */
- if(easy_owns_conn) {
-
- /* multi_done() clears the association between the easy handle and the
- connection.
-
- Note that this ignores the return code simply because there's
- nothing really useful to do with it anyway! */
- (void)multi_done(data, data->result, premature);
- }
+ Note that this ignores the return code simply because there's
+ nothing really useful to do with it anyway! */
+ (void)multi_done(data, data->result, premature);
}
/* The timer must be shut down before data->multi is set to NULL, else the
@@ -802,7 +792,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* change state without using multistate(), only to make singlesocket() do
what we want */
- data->mstate = CURLM_STATE_COMPLETED;
+ data->mstate = MSTATE_COMPLETED;
singlesocket(multi, easy); /* to let the application know what sockets that
vanish with this handle */
@@ -840,6 +830,17 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
}
}
+ /* Remove from the pending list if it is there. Otherwise this will
+ remain on the pending list forever due to the state change. */
+ for(e = multi->pending.head; e; e = e->next) {
+ struct Curl_easy *curr_data = e->ptr;
+
+ if(curr_data == data) {
+ Curl_llist_remove(&multi->pending, e, NULL);
+ break;
+ }
+ }
+
/* make the previous node point to our next */
if(data->prev)
data->prev->next = data->next;
@@ -856,6 +857,8 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
We do not touch the easy handle here! */
multi->num_easy--; /* one less to care about now */
+ process_pending_handles(multi);
+
Curl_update_timer(multi);
return CURLM_OK;
}
@@ -875,8 +878,10 @@ bool Curl_multiplex_wanted(const struct Curl_multi *multi)
void Curl_detach_connnection(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
- if(conn)
+ if(conn) {
Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
+ Curl_ssl_detach_conn(data, conn);
+ }
data->conn = NULL;
}
@@ -893,6 +898,9 @@ void Curl_attach_connnection(struct Curl_easy *data,
data->conn = conn;
Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
&data->conn_queue);
+ if(conn->handler->attach)
+ conn->handler->attach(data, conn);
+ Curl_ssl_associate_conn(data, conn);
}
static int waitconnect_getsock(struct connectdata *conn,
@@ -905,7 +913,7 @@ static int waitconnect_getsock(struct connectdata *conn,
#ifdef USE_SSL
#ifndef CURL_DISABLE_PROXY
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
- return Curl_ssl_getsock(conn, sock);
+ return Curl_ssl->getsock(conn, sock);
#endif
#endif
@@ -933,10 +941,8 @@ static int waitproxyconnect_getsock(struct connectdata *conn,
{
sock[0] = conn->sock[FIRSTSOCKET];
- /* when we've sent a CONNECT to a proxy, we should rather wait for the
- socket to become readable to be able to get the response headers */
if(conn->connect_state)
- return GETSOCK_READSOCK(0);
+ return Curl_connect_getsock(conn);
return GETSOCK_WRITESOCK(0);
}
@@ -984,40 +990,33 @@ static int multi_getsock(struct Curl_easy *data,
if(!conn)
return 0;
- if(data->mstate > CURLM_STATE_CONNECT &&
- data->mstate < CURLM_STATE_COMPLETED) {
- /* Set up ownership correctly */
- data->conn->data = data;
- }
-
switch(data->mstate) {
default:
return 0;
- case CURLM_STATE_WAITRESOLVE:
+ case MSTATE_RESOLVING:
return Curl_resolv_getsock(data, socks);
- case CURLM_STATE_PROTOCONNECT:
- case CURLM_STATE_SENDPROTOCONNECT:
+ case MSTATE_PROTOCONNECTING:
+ case MSTATE_PROTOCONNECT:
return protocol_getsock(data, conn, socks);
- case CURLM_STATE_DO:
- case CURLM_STATE_DOING:
+ case MSTATE_DO:
+ case MSTATE_DOING:
return doing_getsock(data, conn, socks);
- case CURLM_STATE_WAITPROXYCONNECT:
+ case MSTATE_TUNNELING:
return waitproxyconnect_getsock(conn, socks);
- case CURLM_STATE_WAITCONNECT:
+ case MSTATE_CONNECTING:
return waitconnect_getsock(conn, socks);
- case CURLM_STATE_DO_MORE:
+ case MSTATE_DOING_MORE:
return domore_getsock(data, conn, socks);
- case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
- to waiting for the same as the *PERFORM
- states */
- case CURLM_STATE_PERFORM:
+ case MSTATE_DID: /* since is set after DO is completed, we switch to
+ waiting for the same as the PERFORMING state */
+ case MSTATE_PERFORMING:
return Curl_single_getsock(data, conn, socks);
}
@@ -1093,6 +1092,10 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
struct pollfd *ufds = &a_few_on_stack[0];
bool ufds_malloc = FALSE;
+#ifdef USE_WINSOCK
+ WSANETWORKEVENTS wsa_events;
+ DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
+#endif
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -1111,11 +1114,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
- if(bitmap & GETSOCK_READSOCK(i)) {
+ if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
++nfds;
s = sockbunch[i];
}
- if(bitmap & GETSOCK_WRITESOCK(i)) {
+ if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
++nfds;
s = sockbunch[i];
}
@@ -1138,7 +1141,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
nfds += extra_nfds; /* add the externally provided ones */
#ifdef ENABLE_WAKEUP
+#ifdef USE_WINSOCK
+ if(use_wakeup) {
+#else
if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
+#endif
++nfds;
}
#endif
@@ -1166,22 +1173,40 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
-
+#ifdef USE_WINSOCK
+ long mask = 0;
+#endif
if(bitmap & GETSOCK_READSOCK(i)) {
- ufds[nfds].fd = sockbunch[i];
+ s = sockbunch[i];
+#ifdef USE_WINSOCK
+ mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
+#endif
+ ufds[nfds].fd = s;
ufds[nfds].events = POLLIN;
++nfds;
- s = sockbunch[i];
}
if(bitmap & GETSOCK_WRITESOCK(i)) {
- ufds[nfds].fd = sockbunch[i];
+ s = sockbunch[i];
+#ifdef USE_WINSOCK
+ mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
+ send(s, NULL, 0, 0); /* reset FD_WRITE */
+#endif
+ ufds[nfds].fd = s;
ufds[nfds].events = POLLOUT;
++nfds;
- s = sockbunch[i];
}
+ /* s is only set if either being readable or writable is checked */
if(s == CURL_SOCKET_BAD) {
+ /* break on entry not checked for being readable or writable */
break;
}
+#ifdef USE_WINSOCK
+ if(WSAEventSelect(s, multi->wsa_event, mask) != 0) {
+ if(ufds_malloc)
+ free(ufds);
+ return CURLM_INTERNAL_ERROR;
+ }
+#endif
}
data = data->next; /* check next handle */
@@ -1190,6 +1215,22 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
/* Add external file descriptions from poll-like struct curl_waitfd */
for(i = 0; i < extra_nfds; i++) {
+#ifdef USE_WINSOCK
+ long mask = 0;
+ if(extra_fds[i].events & CURL_WAIT_POLLIN)
+ mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
+ if(extra_fds[i].events & CURL_WAIT_POLLPRI)
+ mask |= FD_OOB;
+ if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
+ mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
+ send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */
+ }
+ if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
+ if(ufds_malloc)
+ free(ufds);
+ return CURLM_INTERNAL_ERROR;
+ }
+#endif
ufds[nfds].fd = extra_fds[i].fd;
ufds[nfds].events = 0;
if(extra_fds[i].events & CURL_WAIT_POLLIN)
@@ -1202,25 +1243,62 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
}
#ifdef ENABLE_WAKEUP
+#ifndef USE_WINSOCK
if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
ufds[nfds].fd = multi->wakeup_pair[0];
ufds[nfds].events = POLLIN;
++nfds;
}
#endif
+#endif
+#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
+ if(nfds || use_wakeup) {
+#else
if(nfds) {
- /* wait... */
- int pollrc = Curl_poll(ufds, nfds, timeout_ms);
+#endif
+ int pollrc;
+#ifdef USE_WINSOCK
+ if(nfds)
+ 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) {
retcode = pollrc;
+#ifdef USE_WINSOCK
+ }
+ /* With WinSock, we have to run the following section unconditionally
+ to call WSAEventSelect(fd, event, 0) on all the sockets */
+ {
+#endif
/* copy revents results from the poll to the curl_multi_wait poll
struct, the bit values of the actual underlying poll() implementation
may not be the same as the ones in the public libcurl API! */
for(i = 0; i < extra_nfds; i++) {
- unsigned short mask = 0;
unsigned r = ufds[curlfds + i].revents;
-
+ unsigned short mask = 0;
+#ifdef USE_WINSOCK
+ wsa_events.lNetworkEvents = 0;
+ if(WSAEnumNetworkEvents(extra_fds[i].fd, 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)
+ retcode++;
+ }
+ WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
+ if(pollrc <= 0)
+ continue;
+#endif
if(r & POLLIN)
mask |= CURL_WAIT_POLLIN;
if(r & POLLOUT)
@@ -1230,6 +1308,35 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
extra_fds[i].revents = mask;
}
+#ifdef USE_WINSOCK
+ /* Count up all our own sockets that had activity,
+ and remove them from the event. */
+ if(curlfds) {
+ data = multi->easyp;
+ while(data) {
+ bitmap = multi_getsock(data, sockbunch);
+
+ for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
+ 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)
+ retcode++;
+ }
+ WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
+ }
+ else {
+ /* break on entry not checked for being readable or writable */
+ break;
+ }
+ }
+
+ data = data->next;
+ }
+ }
+
+ WSAResetEvent(multi->wsa_event);
+#else
#ifdef ENABLE_WAKEUP
if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
if(ufds[curlfds + extra_nfds].revents & POLLIN) {
@@ -1242,10 +1349,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
when there is no more data, breaking the loop. */
nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
if(nread <= 0) {
-#ifndef USE_WINSOCK
if(nread < 0 && EINTR == SOCKERRNO)
continue;
-#endif
break;
}
}
@@ -1254,6 +1359,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
}
}
#endif
+#endif
}
}
@@ -1261,10 +1367,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
free(ufds);
if(ret)
*ret = retcode;
- if(!extrawait || nfds)
- /* if any socket was checked */
- ;
- else {
+#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
+ if(extrawait && !nfds && !use_wakeup) {
+#else
+ if(extrawait && !nfds) {
+#endif
long sleep_ms = 0;
/* Avoid busy-looping when there's nothing particular to wait for */
@@ -1313,6 +1420,10 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
return CURLM_BAD_HANDLE;
#ifdef ENABLE_WAKEUP
+#ifdef USE_WINSOCK
+ if(WSASetEvent(multi->wsa_event))
+ return CURLM_OK;
+#else
/* the wakeup_pair variable is only written during init and cleanup,
making it safe to access from another thread after the init part
and before cleanup */
@@ -1346,6 +1457,7 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
}
}
#endif
+#endif
return CURLM_WAKEUP_FAILURE;
}
@@ -1383,7 +1495,7 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
Curl_init_do(data, NULL);
/* take this handle to the perform state right away */
- multistate(data, CURLM_STATE_PERFORM);
+ multistate(data, MSTATE_PERFORMING);
Curl_attach_connnection(data, conn);
k->keepon |= KEEP_RECV; /* setup to receive! */
}
@@ -1397,7 +1509,6 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
DEBUGASSERT(conn);
DEBUGASSERT(conn->handler);
- DEBUGASSERT(conn->data == data);
if(conn->handler->do_it)
/* generic protocol-specific function pointer set in curl_connect() */
@@ -1578,31 +1689,30 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
process_pending_handles(multi); /* multiplexed */
}
- if(data->mstate > CURLM_STATE_CONNECT &&
- data->mstate < CURLM_STATE_COMPLETED) {
+ if(data->mstate > MSTATE_CONNECT &&
+ data->mstate < MSTATE_COMPLETED) {
/* Make sure we set the connection's current owner */
DEBUGASSERT(data->conn);
if(!data->conn)
return CURLM_INTERNAL_ERROR;
- data->conn->data = data;
}
if(data->conn &&
- (data->mstate >= CURLM_STATE_CONNECT) &&
- (data->mstate < CURLM_STATE_COMPLETED)) {
+ (data->mstate >= MSTATE_CONNECT) &&
+ (data->mstate < MSTATE_COMPLETED)) {
/* we need to wait for the connect state as only then is the start time
stored, but we must not check already completed handles */
timeout_ms = Curl_timeleft(data, nowp,
- (data->mstate <= CURLM_STATE_DO)?
+ (data->mstate <= MSTATE_DO)?
TRUE:FALSE);
if(timeout_ms < 0) {
/* Handle timed out */
- if(data->mstate == CURLM_STATE_WAITRESOLVE)
+ if(data->mstate == MSTATE_RESOLVING)
failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds",
Curl_timediff(*nowp, data->progress.t_startsingle));
- else if(data->mstate == CURLM_STATE_WAITCONNECT)
+ else if(data->mstate == MSTATE_CONNECTING)
failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds",
Curl_timediff(*nowp, data->progress.t_startsingle));
@@ -1625,7 +1735,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
/* Force connection closed if the connection has indeed been used */
- if(data->mstate > CURLM_STATE_DO) {
+ if(data->mstate > MSTATE_DO) {
streamclose(data->conn, "Disconnected with pending data");
stream_error = TRUE;
}
@@ -1637,24 +1747,24 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
switch(data->mstate) {
- case CURLM_STATE_INIT:
+ case MSTATE_INIT:
/* init this transfer. */
result = Curl_pretransfer(data);
if(!result) {
/* after init, go CONNECT */
- multistate(data, CURLM_STATE_CONNECT);
+ multistate(data, MSTATE_CONNECT);
*nowp = Curl_pgrsTime(data, TIMER_STARTOP);
rc = CURLM_CALL_MULTI_PERFORM;
}
break;
- case CURLM_STATE_CONNECT_PEND:
+ case MSTATE_PENDING:
/* We will stay here until there is a connection available. Then
- we try again in the CURLM_STATE_CONNECT state. */
+ we try again in the MSTATE_CONNECT state. */
break;
- case CURLM_STATE_CONNECT:
+ case MSTATE_CONNECT:
/* Connect. We want to get a connection identifier filled in. */
/* init this transfer. */
result = Curl_preconnect(data);
@@ -1672,7 +1782,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(CURLE_NO_CONNECTION_AVAILABLE == result) {
/* There was no connection available. We will go to the pending
state and wait for an available connection. */
- multistate(data, CURLM_STATE_CONNECT_PEND);
+ multistate(data, MSTATE_PENDING);
/* add this handle to the list of connect-pending handles */
Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
@@ -1689,7 +1799,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result) {
if(async)
/* We're now waiting for an asynchronous name lookup */
- multistate(data, CURLM_STATE_WAITRESOLVE);
+ multistate(data, MSTATE_RESOLVING);
else {
/* after the connect has been sent off, go WAITCONNECT unless the
protocol connect is already done and we can go directly to
@@ -1697,20 +1807,20 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
rc = CURLM_CALL_MULTI_PERFORM;
if(protocol_connected)
- multistate(data, CURLM_STATE_DO);
+ multistate(data, MSTATE_DO);
else {
#ifndef CURL_DISABLE_HTTP
if(Curl_connect_ongoing(data->conn))
- multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ multistate(data, MSTATE_TUNNELING);
else
#endif
- multistate(data, CURLM_STATE_WAITCONNECT);
+ multistate(data, MSTATE_CONNECTING);
}
}
}
break;
- case CURLM_STATE_WAITRESOLVE:
+ case MSTATE_RESOLVING:
/* awaiting an asynch name resolve to complete */
{
struct Curl_dns_entry *dns = NULL;
@@ -1764,14 +1874,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* call again please so that we get the next socket setup */
rc = CURLM_CALL_MULTI_PERFORM;
if(protocol_connected)
- multistate(data, CURLM_STATE_DO);
+ multistate(data, MSTATE_DO);
else {
#ifndef CURL_DISABLE_HTTP
if(Curl_connect_ongoing(data->conn))
- multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ multistate(data, MSTATE_TUNNELING);
else
#endif
- multistate(data, CURLM_STATE_WAITCONNECT);
+ multistate(data, MSTATE_CONNECTING);
}
}
}
@@ -1785,7 +1895,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break;
#ifndef CURL_DISABLE_HTTP
- case CURLM_STATE_WAITPROXYCONNECT:
+ case MSTATE_TUNNELING:
/* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
DEBUGASSERT(data->conn);
result = Curl_http_connect(data, &protocol_connected);
@@ -1795,7 +1905,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* connect back to proxy again */
result = CURLE_OK;
multi_done(data, CURLE_OK, FALSE);
- multistate(data, CURLM_STATE_CONNECT);
+ multistate(data, MSTATE_CONNECT);
}
else
#endif
@@ -1808,7 +1918,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
Curl_connect_complete(data->conn)) {
rc = CURLM_CALL_MULTI_PERFORM;
/* initiate protocol connect phase */
- multistate(data, CURLM_STATE_SENDPROTOCONNECT);
+ multistate(data, MSTATE_PROTOCONNECT);
}
}
else
@@ -1816,7 +1926,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break;
#endif
- case CURLM_STATE_WAITCONNECT:
+ case MSTATE_CONNECTING:
/* awaiting a completion of an asynch TCP connect */
DEBUGASSERT(data->conn);
result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
@@ -1828,7 +1938,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
!data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
#endif
Curl_connect_ongoing(data->conn)) {
- multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ multistate(data, MSTATE_TUNNELING);
break;
}
#endif
@@ -1836,10 +1946,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
#ifndef CURL_DISABLE_PROXY
multistate(data,
data->conn->bits.tunnel_proxy?
- CURLM_STATE_WAITPROXYCONNECT:
- CURLM_STATE_SENDPROTOCONNECT);
+ MSTATE_TUNNELING : MSTATE_PROTOCONNECT);
#else
- multistate(data, CURLM_STATE_SENDPROTOCONNECT);
+ multistate(data, MSTATE_PROTOCONNECT);
#endif
}
else if(result) {
@@ -1851,14 +1960,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
break;
- case CURLM_STATE_SENDPROTOCONNECT:
+ case MSTATE_PROTOCONNECT:
result = protocol_connect(data, &protocol_connected);
if(!result && !protocol_connected)
/* switch to waiting state */
- multistate(data, CURLM_STATE_PROTOCONNECT);
+ multistate(data, MSTATE_PROTOCONNECTING);
else if(!result) {
/* protocol connect has completed, go WAITDO or DO */
- multistate(data, CURLM_STATE_DO);
+ multistate(data, MSTATE_DO);
rc = CURLM_CALL_MULTI_PERFORM;
}
else {
@@ -1869,12 +1978,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
break;
- case CURLM_STATE_PROTOCONNECT:
+ case MSTATE_PROTOCONNECTING:
/* protocol-specific connect phase */
result = protocol_connecting(data, &protocol_connected);
if(!result && protocol_connected) {
/* after the connect has completed, go WAITDO or DO */
- multistate(data, CURLM_STATE_DO);
+ multistate(data, MSTATE_DO);
rc = CURLM_CALL_MULTI_PERFORM;
}
else if(result) {
@@ -1885,11 +1994,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
break;
- case CURLM_STATE_DO:
+ case MSTATE_DO:
if(data->set.connect_only) {
/* keep connection open for application to use the socket */
connkeep(data->conn, "CONNECT_ONLY");
- multistate(data, CURLM_STATE_DONE);
+ multistate(data, MSTATE_DONE);
result = CURLE_OK;
rc = CURLM_CALL_MULTI_PERFORM;
}
@@ -1911,7 +2020,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* if there's no connection left, skip the DONE state */
multistate(data, data->conn ?
- CURLM_STATE_DONE : CURLM_STATE_COMPLETED);
+ MSTATE_DONE : MSTATE_COMPLETED);
rc = CURLM_CALL_MULTI_PERFORM;
break;
}
@@ -1919,7 +2028,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
#endif
/* DO was not completed in one function call, we must continue
DOING... */
- multistate(data, CURLM_STATE_DOING);
+ multistate(data, MSTATE_DOING);
rc = CURLM_OK;
}
@@ -1927,12 +2036,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
else if(data->conn->bits.do_more) {
/* we're supposed to do more, but we need to sit down, relax
and wait a little while first */
- multistate(data, CURLM_STATE_DO_MORE);
+ multistate(data, MSTATE_DOING_MORE);
rc = CURLM_OK;
}
else {
- /* we're done with the DO, now DO_DONE */
- multistate(data, CURLM_STATE_DO_DONE);
+ /* we're done with the DO, now DID */
+ multistate(data, MSTATE_DID);
rc = CURLM_CALL_MULTI_PERFORM;
}
}
@@ -1964,7 +2073,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
follow = FOLLOW_RETRY;
drc = Curl_follow(data, newurl, follow);
if(!drc) {
- multistate(data, CURLM_STATE_CONNECT);
+ multistate(data, MSTATE_CONNECT);
rc = CURLM_CALL_MULTI_PERFORM;
result = CURLE_OK;
}
@@ -1994,7 +2103,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
break;
- case CURLM_STATE_DOING:
+ case MSTATE_DOING:
/* we continue DOING until the DO phase is complete */
DEBUGASSERT(data->conn);
result = protocol_doing(data, &dophase_done);
@@ -2002,8 +2111,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(dophase_done) {
/* after DO, go DO_DONE or DO_MORE */
multistate(data, data->conn->bits.do_more?
- CURLM_STATE_DO_MORE:
- CURLM_STATE_DO_DONE);
+ MSTATE_DOING_MORE : MSTATE_DID);
rc = CURLM_CALL_MULTI_PERFORM;
} /* dophase_done */
}
@@ -2015,9 +2123,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
break;
- case CURLM_STATE_DO_MORE:
+ case MSTATE_DOING_MORE:
/*
- * When we are connected, DO MORE and then go DO_DONE
+ * When we are connected, DOING MORE and then go DID
*/
DEBUGASSERT(data->conn);
result = multi_do_more(data, &control);
@@ -2027,8 +2135,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* if positive, advance to DO_DONE
if negative, go back to DOING */
multistate(data, control == 1?
- CURLM_STATE_DO_DONE:
- CURLM_STATE_DOING);
+ MSTATE_DID : MSTATE_DOING);
rc = CURLM_CALL_MULTI_PERFORM;
}
else
@@ -2043,7 +2150,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
break;
- case CURLM_STATE_DO_DONE:
+ case MSTATE_DID:
DEBUGASSERT(data->conn);
if(data->conn->bits.multiplex)
/* Check if we can move pending requests to send pipe */
@@ -2053,7 +2160,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
Having both BAD is a signal to skip immediately to DONE */
if((data->conn->sockfd != CURL_SOCKET_BAD) ||
(data->conn->writesockfd != CURL_SOCKET_BAD))
- multistate(data, CURLM_STATE_PERFORM);
+ multistate(data, MSTATE_PERFORMING);
else {
#ifndef CURL_DISABLE_FTP
if(data->state.wildcardmatch &&
@@ -2061,12 +2168,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->wildcard.state = CURLWC_DONE;
}
#endif
- multistate(data, CURLM_STATE_DONE);
+ multistate(data, MSTATE_DONE);
}
rc = CURLM_CALL_MULTI_PERFORM;
break;
- case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
+ case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
DEBUGASSERT(data->conn);
/* if both rates are within spec, resume transfer */
if(Curl_pgrsUpdate(data))
@@ -2084,7 +2191,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
else {
send_timeout_ms = 0;
- if(data->set.max_send_speed > 0)
+ if(data->set.max_send_speed)
send_timeout_ms =
Curl_pgrsLimitWaitTime(data->progress.uploaded,
data->progress.ul_limit_size,
@@ -2093,7 +2200,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
*nowp);
recv_timeout_ms = 0;
- if(data->set.max_recv_speed > 0)
+ if(data->set.max_recv_speed)
recv_timeout_ms =
Curl_pgrsLimitWaitTime(data->progress.downloaded,
data->progress.dl_limit_size,
@@ -2102,7 +2209,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
*nowp);
if(!send_timeout_ms && !recv_timeout_ms) {
- multistate(data, CURLM_STATE_PERFORM);
+ multistate(data, MSTATE_PERFORMING);
Curl_ratelimit(data, *nowp);
}
else if(send_timeout_ms >= recv_timeout_ms)
@@ -2112,7 +2219,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
break;
- case CURLM_STATE_PERFORM:
+ case MSTATE_PERFORMING:
{
char *newurl = NULL;
bool retry = FALSE;
@@ -2120,7 +2227,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
DEBUGASSERT(data->state.buffer);
/* check if over send speed */
send_timeout_ms = 0;
- if(data->set.max_send_speed > 0)
+ if(data->set.max_send_speed)
send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
data->progress.ul_limit_size,
data->set.max_send_speed,
@@ -2129,7 +2236,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* check if over recv speed */
recv_timeout_ms = 0;
- if(data->set.max_recv_speed > 0)
+ if(data->set.max_recv_speed)
recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
data->progress.dl_limit_size,
data->set.max_recv_speed,
@@ -2138,7 +2245,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(send_timeout_ms || recv_timeout_ms) {
Curl_ratelimit(data, *nowp);
- multistate(data, CURLM_STATE_TOOFAST);
+ multistate(data, MSTATE_RATELIMITING);
if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
else
@@ -2168,17 +2275,18 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
}
else if((CURLE_HTTP2_STREAM == result) &&
- Curl_h2_http_1_1_error(data->conn)) {
+ Curl_h2_http_1_1_error(data)) {
CURLcode ret = Curl_retry_request(data, &newurl);
if(!ret) {
infof(data, "Downgrades to HTTP/1.1!\n");
- data->set.httpversion = CURL_HTTP_VERSION_1_1;
+ streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
+ data->state.httpwant = CURL_HTTP_VERSION_1_1;
/* clear the error message bit too as we ignore the one we got */
data->state.errorbuf = FALSE;
if(!newurl)
/* typically for HTTP_1_1_REQUIRED error on first flight */
- newurl = strdup(data->change.url);
+ newurl = strdup(data->state.url);
/* if we are to retry, set the result to OK and consider the request
as done */
retry = TRUE;
@@ -2228,7 +2336,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* multi_done() might return CURLE_GOT_NOTHING */
result = Curl_follow(data, newurl, follow);
if(!result) {
- multistate(data, CURLM_STATE_CONNECT);
+ multistate(data, MSTATE_CONNECT);
rc = CURLM_CALL_MULTI_PERFORM;
}
free(newurl);
@@ -2251,7 +2359,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
if(!result) {
- multistate(data, CURLM_STATE_DONE);
+ multistate(data, MSTATE_DONE);
rc = CURLM_CALL_MULTI_PERFORM;
}
}
@@ -2266,7 +2374,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break;
}
- case CURLM_STATE_DONE:
+ case MSTATE_DONE:
/* this state is highly transient, so run another loop after this */
rc = CURLM_CALL_MULTI_PERFORM;
@@ -2289,21 +2397,21 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(data->state.wildcardmatch) {
if(data->wildcard.state != CURLWC_DONE) {
/* if a wildcard is set and we are not ending -> lets start again
- with CURLM_STATE_INIT */
- multistate(data, CURLM_STATE_INIT);
+ with MSTATE_INIT */
+ multistate(data, MSTATE_INIT);
break;
}
}
#endif
/* after we have DONE what we're supposed to do, go COMPLETED, and
it doesn't matter what the multi_done() returned! */
- multistate(data, CURLM_STATE_COMPLETED);
+ multistate(data, MSTATE_COMPLETED);
break;
- case CURLM_STATE_COMPLETED:
+ case MSTATE_COMPLETED:
break;
- case CURLM_STATE_MSGSENT:
+ case MSTATE_MSGSENT:
data->result = result;
return CURLM_OK; /* do nothing */
@@ -2312,7 +2420,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
statemachine_end:
- if(data->mstate < CURLM_STATE_COMPLETED) {
+ if(data->mstate < MSTATE_COMPLETED) {
if(result) {
/*
* If an error was returned, and we aren't in completed state now,
@@ -2343,12 +2451,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
Curl_disconnect(data, conn, dead_connection);
}
}
- else if(data->mstate == CURLM_STATE_CONNECT) {
+ else if(data->mstate == MSTATE_CONNECT) {
/* Curl_connect() failed */
(void)Curl_posttransfer(data);
}
- multistate(data, CURLM_STATE_COMPLETED);
+ multistate(data, MSTATE_COMPLETED);
rc = CURLM_CALL_MULTI_PERFORM;
}
/* if there's still a connection to use, call the progress function */
@@ -2359,13 +2467,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
streamclose(data->conn, "Aborted by callback");
/* if not yet in DONE state, go there, otherwise COMPLETED */
- multistate(data, (data->mstate < CURLM_STATE_DONE)?
- CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
+ multistate(data, (data->mstate < MSTATE_DONE)?
+ MSTATE_DONE: MSTATE_COMPLETED);
rc = CURLM_CALL_MULTI_PERFORM;
}
}
- if(CURLM_STATE_COMPLETED == data->mstate) {
+ if(MSTATE_COMPLETED == data->mstate) {
if(data->set.fmultidone) {
/* signal via callback instead */
data->set.fmultidone(data, result);
@@ -2381,7 +2489,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
rc = multi_addmsg(multi, msg);
DEBUGASSERT(!data->conn);
}
- multistate(data, CURLM_STATE_MSGSENT);
+ multistate(data, MSTATE_MSGSENT);
}
} while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
@@ -2492,10 +2600,14 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
Curl_hash_destroy(&multi->hostcache);
Curl_psl_destroy(&multi->psl);
+#ifdef USE_WINSOCK
+ WSACloseEvent(multi->wsa_event);
+#else
#ifdef ENABLE_WAKEUP
sclose(multi->wakeup_pair[0]);
sclose(multi->wakeup_pair[1]);
#endif
+#endif
free(multi);
return CURLM_OK;
@@ -2554,7 +2666,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
curl_socket_t s;
int num;
unsigned int curraction;
- int actions[MAX_SOCKSPEREASYHANDLE];
+ unsigned char actions[MAX_SOCKSPEREASYHANDLE];
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
socks[i] = CURL_SOCKET_BAD;
@@ -2571,9 +2683,9 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
(curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
i++) {
- unsigned int action = CURL_POLL_NONE;
- unsigned int prevaction = 0;
- unsigned int comboaction;
+ unsigned char action = CURL_POLL_NONE;
+ unsigned char prevaction = 0;
+ int comboaction;
bool sincebefore = FALSE;
s = socks[i];
@@ -2631,10 +2743,10 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
}
comboaction = (entry->writers? CURL_POLL_OUT : 0) |
- (entry->readers ? CURL_POLL_IN : 0);
+ (entry->readers ? CURL_POLL_IN : 0);
/* socket existed before and has the same action set as before */
- if(sincebefore && (entry->action == comboaction))
+ if(sincebefore && ((int)entry->action == comboaction))
/* same, continue */
continue;
@@ -2667,7 +2779,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
/* if this is NULL here, the socket has been closed and notified so
already by Curl_multi_closed() */
if(entry) {
- int oldactions = data->actions[i];
+ unsigned char oldactions = data->actions[i];
/* this socket has been removed. Decrease user count */
entry->users--;
if(oldactions & CURL_POLL_OUT)
@@ -2692,7 +2804,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
} /* for loop over numsocks */
memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
- memcpy(data->actions, actions, num*sizeof(int));
+ memcpy(data->actions, actions, num*sizeof(char));
data->numsocks = num;
return CURLM_OK;
}
@@ -3344,9 +3456,9 @@ static void process_pending_handles(struct Curl_multi *multi)
if(e) {
struct Curl_easy *data = e->ptr;
- DEBUGASSERT(data->mstate == CURLM_STATE_CONNECT_PEND);
+ DEBUGASSERT(data->mstate == MSTATE_PENDING);
- multistate(data, CURLM_STATE_CONNECT);
+ multistate(data, MSTATE_CONNECT);
/* Remove this node from the list */
Curl_llist_remove(&multi->pending, e, NULL);
@@ -3384,7 +3496,7 @@ void Curl_multi_dump(struct Curl_multi *multi)
fprintf(stderr, "* Multi status: %d handles, %d alive\n",
multi->num_easy, multi->num_alive);
for(data = multi->easyp; data; data = data->next) {
- if(data->mstate < CURLM_STATE_COMPLETED) {
+ if(data->mstate < MSTATE_COMPLETED) {
/* only display handles that are not completed */
fprintf(stderr, "handle %p, state %s, %d sockets\n",
(void *)data,
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index f28c5899b..96b84749f 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -40,27 +40,26 @@ struct Curl_message {
well!
*/
typedef enum {
- CURLM_STATE_INIT, /* 0 - start in this state */
- CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */
- CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */
- CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */
- CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */
- CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization
- to complete and/or proxy CONNECT to
- finalize */
- CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
- CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
- phase */
- CURLM_STATE_DO, /* 8 - start send off the request (part 1) */
- CURLM_STATE_DOING, /* 9 - sending off the request (part 1) */
- CURLM_STATE_DO_MORE, /* 10 - send off the request (part 2) */
- CURLM_STATE_DO_DONE, /* 11 - done sending off request */
- CURLM_STATE_PERFORM, /* 12 - transfer data */
- CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */
- CURLM_STATE_DONE, /* 14 - post data transfer operation */
- CURLM_STATE_COMPLETED, /* 15 - operation complete */
- CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */
- CURLM_STATE_LAST /* 17 - not a true state, never use this */
+ MSTATE_INIT, /* 0 - start in this state */
+ MSTATE_PENDING, /* 1 - no connections, waiting for one */
+ MSTATE_CONNECT, /* 2 - resolve/connect has been sent off */
+ MSTATE_RESOLVING, /* 3 - awaiting the resolve to finalize */
+ MSTATE_CONNECTING, /* 4 - awaiting the TCP connect to finalize */
+ MSTATE_TUNNELING, /* 5 - awaiting HTTPS proxy SSL initialization to
+ complete and/or proxy CONNECT to finalize */
+ MSTATE_PROTOCONNECT, /* 6 - initiate protocol connect procedure */
+ MSTATE_PROTOCONNECTING, /* 7 - completing the protocol-specific connect
+ phase */
+ MSTATE_DO, /* 8 - start send off the request (part 1) */
+ MSTATE_DOING, /* 9 - sending off the request (part 1) */
+ MSTATE_DOING_MORE, /* 10 - send off the request (part 2) */
+ MSTATE_DID, /* 11 - done sending off request */
+ MSTATE_PERFORMING, /* 12 - transfer data */
+ MSTATE_RATELIMITING, /* 13 - wait because limit-rate exceeded */
+ MSTATE_DONE, /* 14 - post data transfer operation */
+ MSTATE_COMPLETED, /* 15 - operation complete */
+ MSTATE_MSGSENT, /* 16 - the operation complete message is sent */
+ MSTATE_LAST /* 17 - not a true state, never use this */
} CURLMstate;
/* we support N sockets per easy handle. Set the corresponding bit to what
@@ -71,8 +70,7 @@ typedef enum {
#define CURLPIPE_ANY (CURLPIPE_MULTIPLEX)
-#if defined(USE_SOCKETPAIR) && !defined(USE_BLOCKING_SOCKETS) && \
- !defined(CURL_DISABLE_SOCKETPAIR)
+#if !defined(CURL_DISABLE_SOCKETPAIR)
#define ENABLE_WAKEUP
#endif
@@ -96,7 +94,7 @@ struct Curl_multi {
struct Curl_llist msglist; /* a list of messages from completed transfers */
struct Curl_llist pending; /* Curl_easys that are in the
- CURLM_STATE_CONNECT_PEND state */
+ MSTATE_PENDING state */
/* callback function and user data pointer for the *socket() API */
curl_socket_callback socket_cb;
@@ -142,10 +140,14 @@ struct Curl_multi {
previous callback */
unsigned int max_concurrent_streams;
+#ifdef USE_WINSOCK
+ WSAEVENT wsa_event; /* winsock event used for waits */
+#else
#ifdef ENABLE_WAKEUP
curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup
0 is used for read, 1 is used for write */
#endif
+#endif
/* multiplexing wanted */
bool multiplexing;
bool recheckstate; /* see Curl_multi_connchanged */
diff --git a/Utilities/cmcurl/lib/non-ascii.c b/Utilities/cmcurl/lib/non-ascii.c
index 30c240b63..932cf89ee 100644
--- a/Utilities/cmcurl/lib/non-ascii.c
+++ b/Utilities/cmcurl/lib/non-ascii.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -127,7 +127,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
&output_ptr, &out_bytes);
if(!data)
iconv_close(tmpcd);
- if((rc == ICONV_ERROR) || (in_bytes != 0)) {
+ if((rc == ICONV_ERROR) || (in_bytes)) {
failf(data,
"The Curl_convert_to_network iconv call failed with errno %i: %s",
errno, strerror(errno));
@@ -193,7 +193,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
&output_ptr, &out_bytes);
if(!data)
iconv_close(tmpcd);
- if((rc == ICONV_ERROR) || (in_bytes != 0)) {
+ if((rc == ICONV_ERROR) || (in_bytes)) {
failf(data,
"Curl_convert_from_network iconv call failed with errno %i: %s",
errno, strerror(errno));
@@ -260,7 +260,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
&output_ptr, &out_bytes);
if(!data)
iconv_close(tmpcd);
- if((rc == ICONV_ERROR) || (in_bytes != 0)) {
+ if((rc == ICONV_ERROR) || (in_bytes)) {
failf(data,
"The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
errno, strerror(errno));
diff --git a/Utilities/cmcurl/lib/nonblock.c b/Utilities/cmcurl/lib/nonblock.c
index 4a7bde504..fda2e9ad7 100644
--- a/Utilities/cmcurl/lib/nonblock.c
+++ b/Utilities/cmcurl/lib/nonblock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -47,13 +47,7 @@
int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */)
{
-#if defined(USE_BLOCKING_SOCKETS)
- (void)sockfd;
- (void)nonblock;
- return 0; /* returns success */
-
-#elif defined(HAVE_FCNTL_O_NONBLOCK)
-
+#if defined(HAVE_FCNTL_O_NONBLOCK)
/* most recent unix versions */
int flags;
flags = sfcntl(sockfd, F_GETFL, 0);
diff --git a/Utilities/cmcurl/lib/openldap.c b/Utilities/cmcurl/lib/openldap.c
index 4070bbf88..0b8bc34a0 100644
--- a/Utilities/cmcurl/lib/openldap.c
+++ b/Utilities/cmcurl/lib/openldap.c
@@ -76,16 +76,16 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
LDAP **ld);
#endif
-static CURLcode ldap_setup_connection(struct Curl_easy *data,
- struct connectdata *conn);
-static CURLcode ldap_do(struct Curl_easy *data, bool *done);
-static CURLcode ldap_done(struct Curl_easy *data, CURLcode, bool);
-static CURLcode ldap_connect(struct Curl_easy *data, bool *done);
-static CURLcode ldap_connecting(struct Curl_easy *data, bool *done);
-static CURLcode ldap_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead);
+static CURLcode oldap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode oldap_do(struct Curl_easy *data, bool *done);
+static CURLcode oldap_done(struct Curl_easy *data, CURLcode, bool);
+static CURLcode oldap_connect(struct Curl_easy *data, bool *done);
+static CURLcode oldap_connecting(struct Curl_easy *data, bool *done);
+static CURLcode oldap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
-static Curl_recv ldap_recv;
+static Curl_recv oldap_recv;
/*
* LDAP protocol handler.
@@ -93,20 +93,21 @@ static Curl_recv ldap_recv;
const struct Curl_handler Curl_handler_ldap = {
"LDAP", /* scheme */
- ldap_setup_connection, /* setup_connection */
- ldap_do, /* do_it */
- ldap_done, /* done */
+ oldap_setup_connection, /* setup_connection */
+ oldap_do, /* do_it */
+ oldap_done, /* done */
ZERO_NULL, /* do_more */
- ldap_connect, /* connect_it */
- ldap_connecting, /* connecting */
+ oldap_connect, /* connect_it */
+ oldap_connecting, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- ldap_disconnect, /* disconnect */
+ oldap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
CURLPROTO_LDAP, /* family */
@@ -120,20 +121,21 @@ const struct Curl_handler Curl_handler_ldap = {
const struct Curl_handler Curl_handler_ldaps = {
"LDAPS", /* scheme */
- ldap_setup_connection, /* setup_connection */
- ldap_do, /* do_it */
- ldap_done, /* done */
+ oldap_setup_connection, /* setup_connection */
+ oldap_do, /* do_it */
+ oldap_done, /* done */
ZERO_NULL, /* do_more */
- ldap_connect, /* connect_it */
- ldap_connecting, /* connecting */
+ oldap_connect, /* connect_it */
+ oldap_connecting, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- ldap_disconnect, /* disconnect */
+ oldap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_LDAPS, /* defport */
CURLPROTO_LDAPS, /* protocol */
CURLPROTO_LDAP, /* family */
@@ -171,15 +173,15 @@ struct ldapreqinfo {
int nument;
};
-static CURLcode ldap_setup_connection(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode oldap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct ldapconninfo *li;
LDAPURLDesc *lud;
int rc, proto;
CURLcode status;
- rc = ldap_url_parse(data->change.url, &lud);
+ rc = ldap_url_parse(data->state.url, &lud);
if(rc != LDAP_URL_SUCCESS) {
const char *msg = "url parsing problem";
status = CURLE_URL_MALFORMAT;
@@ -207,7 +209,7 @@ static CURLcode ldap_setup_connection(struct Curl_easy *data,
static Sockbuf_IO ldapsb_tls;
#endif
-static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
+static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
@@ -255,7 +257,7 @@ static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
-static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
+static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
@@ -278,7 +280,7 @@ static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
if(!li->sslinst) {
Sockbuf *sb;
ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
- ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn);
+ ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
li->sslinst = TRUE;
li->recv = conn->recv[FIRSTSOCKET];
li->send = conn->send[FIRSTSOCKET];
@@ -354,21 +356,28 @@ static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
if(info)
ldap_memfree(info);
- conn->recv[FIRSTSOCKET] = ldap_recv;
+ conn->recv[FIRSTSOCKET] = oldap_recv;
*done = TRUE;
return CURLE_OK;
}
-static CURLcode ldap_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead_connection)
+static CURLcode oldap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
struct ldapconninfo *li = conn->proto.ldapc;
(void) dead_connection;
- (void) data;
if(li) {
if(li->ld) {
+#ifdef USE_SSL
+ if(conn->ssl[FIRSTSOCKET].use) {
+ Sockbuf *sb;
+ ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
+ ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
+ }
+#endif
ldap_unbind_ext(li->ld, NULL, NULL);
li->ld = NULL;
}
@@ -378,7 +387,7 @@ static CURLcode ldap_disconnect(struct Curl_easy *data,
return CURLE_OK;
}
-static CURLcode ldap_do(struct Curl_easy *data, bool *done)
+static CURLcode oldap_do(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
@@ -390,9 +399,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
connkeep(conn, "OpenLDAP do");
- infof(data, "LDAP local: %s\n", data->change.url);
+ infof(data, "LDAP local: %s\n", data->state.url);
- rc = ldap_url_parse(data->change.url, &ludp);
+ rc = ldap_url_parse(data->state.url, &ludp);
if(rc != LDAP_URL_SUCCESS) {
const char *msg = "url parsing problem";
status = CURLE_URL_MALFORMAT;
@@ -423,8 +432,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
-static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
- bool premature)
+static CURLcode oldap_done(struct Curl_easy *data, CURLcode res,
+ bool premature)
{
struct connectdata *conn = data->conn;
struct ldapreqinfo *lr = data->req.p.ldap;
@@ -446,8 +455,8 @@ static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
return CURLE_OK;
}
-static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
- size_t len, CURLcode *err)
+static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
+ size_t len, CURLcode *err)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
@@ -543,7 +552,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) {
int i;
- if(bv.bv_val == NULL)
+ if(!bv.bv_val)
break;
if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
@@ -551,7 +560,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
else
binary = 0;
- if(bvals == NULL) {
+ if(!bvals) {
writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(writeerr) {
*err = writeerr;
@@ -660,7 +669,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
data->req.bytecount += bvals[i].bv_len + 1;
}
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(writeerr) {
*err = writeerr;
return -1;
@@ -669,14 +678,14 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
data->req.bytecount++;
}
ber_memfree(bvals);
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(writeerr) {
*err = writeerr;
return -1;
}
data->req.bytecount++;
}
- writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(writeerr) {
*err = writeerr;
return -1;
@@ -716,8 +725,8 @@ ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
{
(void)arg;
if(opt == LBER_SB_OPT_DATA_READY) {
- struct connectdata *conn = sbiod->sbiod_pvt;
- return Curl_ssl_data_pending(conn, FIRSTSOCKET);
+ struct Curl_easy *data = sbiod->sbiod_pvt;
+ return Curl_ssl_data_pending(data->conn, FIRSTSOCKET);
}
return 0;
}
@@ -725,14 +734,19 @@ ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
static ber_slen_t
ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
- struct connectdata *conn = sbiod->sbiod_pvt;
- struct ldapconninfo *li = conn->proto.ldapc;
- ber_slen_t ret;
- CURLcode err = CURLE_RECV_ERROR;
+ struct Curl_easy *data = sbiod->sbiod_pvt;
+ ber_slen_t ret = 0;
+ if(data) {
+ struct connectdata *conn = data->conn;
+ if(conn) {
+ struct ldapconninfo *li = conn->proto.ldapc;
+ CURLcode err = CURLE_RECV_ERROR;
- ret = (li->recv)(conn->data, FIRSTSOCKET, buf, len, &err);
- if(ret < 0 && err == CURLE_AGAIN) {
- SET_SOCKERRNO(EWOULDBLOCK);
+ ret = (li->recv)(data, FIRSTSOCKET, buf, len, &err);
+ if(ret < 0 && err == CURLE_AGAIN) {
+ SET_SOCKERRNO(EWOULDBLOCK);
+ }
+ }
}
return ret;
}
@@ -740,14 +754,18 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
static ber_slen_t
ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
- struct connectdata *conn = sbiod->sbiod_pvt;
- struct ldapconninfo *li = conn->proto.ldapc;
- ber_slen_t ret;
- CURLcode err = CURLE_SEND_ERROR;
-
- ret = (li->send)(conn->data, FIRSTSOCKET, buf, len, &err);
- if(ret < 0 && err == CURLE_AGAIN) {
- SET_SOCKERRNO(EWOULDBLOCK);
+ struct Curl_easy *data = sbiod->sbiod_pvt;
+ ber_slen_t ret = 0;
+ if(data) {
+ struct connectdata *conn = data->conn;
+ if(conn) {
+ struct ldapconninfo *li = conn->proto.ldapc;
+ CURLcode err = CURLE_SEND_ERROR;
+ ret = (li->send)(data, FIRSTSOCKET, buf, len, &err);
+ if(ret < 0 && err == CURLE_AGAIN) {
+ SET_SOCKERRNO(EWOULDBLOCK);
+ }
+ }
}
return ret;
}
diff --git a/Utilities/cmcurl/lib/pingpong.h b/Utilities/cmcurl/lib/pingpong.h
index 4f7d7ea6b..8f56f3f86 100644
--- a/Utilities/cmcurl/lib/pingpong.h
+++ b/Utilities/cmcurl/lib/pingpong.h
@@ -33,10 +33,9 @@
struct connectdata;
typedef enum {
- FTPTRANSFER_BODY, /* yes do transfer a body */
- FTPTRANSFER_INFO, /* do still go through to get info/headers */
- FTPTRANSFER_NONE, /* don't get anything and don't get info */
- FTPTRANSFER_LAST /* end of list marker, never used */
+ PPTRANSFER_BODY, /* yes do transfer a body */
+ PPTRANSFER_INFO, /* do still go through to get info/headers */
+ PPTRANSFER_NONE /* don't get anything and don't get info */
} curl_pp_transfer;
/*
diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 0ed3d3ee1..9b6ea6480 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -131,6 +131,7 @@ const struct Curl_handler Curl_handler_pop3 = {
pop3_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_POP3, /* defport */
CURLPROTO_POP3, /* protocol */
CURLPROTO_POP3, /* family */
@@ -159,6 +160,7 @@ const struct Curl_handler Curl_handler_pop3s = {
pop3_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_POP3S, /* defport */
CURLPROTO_POP3S, /* protocol */
CURLPROTO_POP3, /* family */
@@ -571,12 +573,12 @@ static CURLcode pop3_perform_command(struct Curl_easy *data)
const char *command = NULL;
/* Calculate the default command */
- if(pop3->id[0] == '\0' || data->set.ftp_list_only) {
+ if(pop3->id[0] == '\0' || data->set.list_only) {
command = "LIST";
if(pop3->id[0] != '\0')
/* Message specific LIST so skip the BODY transfer */
- pop3->transfer = FTPTRANSFER_INFO;
+ pop3->transfer = PPTRANSFER_INFO;
}
else
command = "RETR";
@@ -709,7 +711,7 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
for(;;) {
size_t llen;
size_t wordlen;
- unsigned int mechbit;
+ unsigned short mechbit;
while(len &&
(*line == ' ' || *line == '\t' ||
@@ -916,7 +918,7 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
the strip counter here so that these bytes won't be delivered. */
pop3c->strip = 2;
- if(pop3->transfer == FTPTRANSFER_BODY) {
+ if(pop3->transfer == PPTRANSFER_BODY) {
/* POP3 download */
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
@@ -1150,7 +1152,7 @@ static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
Curl_safefree(pop3->custom);
/* Clear the transfer mode for the next request */
- pop3->transfer = FTPTRANSFER_BODY;
+ pop3->transfer = PPTRANSFER_BODY;
return result;
}
@@ -1174,7 +1176,7 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
if(data->set.opt_no_body) {
/* Requested no body means no transfer */
- pop3->transfer = FTPTRANSFER_INFO;
+ pop3->transfer = PPTRANSFER_INFO;
}
*dophase_done = FALSE; /* not done yet */
@@ -1515,8 +1517,17 @@ CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread)
if(prev) {
/* If the partial match was the CRLF and dot then only write the CRLF
as the server would have inserted the dot */
- result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB,
- strip_dot ? prev - 1 : prev);
+ if(strip_dot && prev - 1 > 0) {
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB,
+ prev - 1);
+ }
+ else if(!strip_dot) {
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB,
+ prev);
+ }
+ else {
+ result = CURLE_OK;
+ }
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index 55e8ded04..4bcd615eb 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -85,7 +85,7 @@ static char *max5data(curl_off_t bytes, char *max5)
CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
(bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
+#if (SIZEOF_CURL_OFF_T > 4)
else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
/* 'XXXXM' is good until we're at 10000MB or above */
@@ -241,6 +241,8 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
data->progress.is_t_startransfer_set = false;
data->progress.ul_limit_start = data->progress.start;
data->progress.dl_limit_start = data->progress.start;
+ data->progress.ul_limit_size = 0;
+ data->progress.dl_limit_size = 0;
data->progress.downloaded = 0;
data->progress.uploaded = 0;
/* clear all bits except HIDE and HEADERS_OUT */
@@ -321,14 +323,14 @@ void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
void Curl_ratelimit(struct Curl_easy *data, struct curltime now)
{
/* don't set a new stamp unless the time since last update is long enough */
- if(data->set.max_recv_speed > 0) {
+ if(data->set.max_recv_speed) {
if(Curl_timediff(now, data->progress.dl_limit_start) >=
MIN_RATE_LIMIT_PERIOD) {
data->progress.dl_limit_start = now;
data->progress.dl_limit_size = data->progress.downloaded;
}
}
- if(data->set.max_send_speed > 0) {
+ if(data->set.max_send_speed) {
if(Curl_timediff(now, data->progress.ul_limit_start) >=
MIN_RATE_LIMIT_PERIOD) {
data->progress.ul_limit_start = now;
@@ -369,94 +371,82 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
}
}
+/* returns the average speed in bytes / second */
+static curl_off_t trspeed(curl_off_t size, /* number of bytes */
+ curl_off_t us) /* microseconds */
+{
+ if(us < 1)
+ return size * 1000000;
+ return (curl_off_t)((long double)size/us * 1000000);
+}
+
/* returns TRUE if it's time to show the progress meter */
static bool progress_calc(struct Curl_easy *data, struct curltime now)
{
- curl_off_t timespent;
- curl_off_t timespent_ms; /* milliseconds */
- curl_off_t dl = data->progress.downloaded;
- curl_off_t ul = data->progress.uploaded;
bool timetoshow = FALSE;
+ struct Progress * const p = &data->progress;
- /* The time spent so far (from the start) */
- data->progress.timespent = Curl_timediff_us(now, data->progress.start);
- timespent = (curl_off_t)data->progress.timespent/1000000; /* seconds */
- timespent_ms = (curl_off_t)data->progress.timespent/1000; /* ms */
-
- /* The average download speed this far */
- if(dl < CURL_OFF_T_MAX/1000)
- data->progress.dlspeed = (dl * 1000 / (timespent_ms>0?timespent_ms:1));
- else
- data->progress.dlspeed = (dl / (timespent>0?timespent:1));
-
- /* The average upload speed this far */
- if(ul < CURL_OFF_T_MAX/1000)
- data->progress.ulspeed = (ul * 1000 / (timespent_ms>0?timespent_ms:1));
- else
- data->progress.ulspeed = (ul / (timespent>0?timespent:1));
+ /* The time spent so far (from the start) in microseconds */
+ p->timespent = Curl_timediff_us(now, p->start);
+ p->dlspeed = trspeed(p->downloaded, p->timespent);
+ p->ulspeed = trspeed(p->uploaded, p->timespent);
/* Calculations done at most once a second, unless end is reached */
- if(data->progress.lastshow != now.tv_sec) {
+ if(p->lastshow != now.tv_sec) {
int countindex; /* amount of seconds stored in the speeder array */
- int nowindex = data->progress.speeder_c% CURR_TIME;
- data->progress.lastshow = now.tv_sec;
+ int nowindex = p->speeder_c% CURR_TIME;
+ p->lastshow = now.tv_sec;
timetoshow = TRUE;
/* Let's do the "current speed" thing, with the dl + ul speeds
combined. Store the speed at entry 'nowindex'. */
- data->progress.speeder[ nowindex ] =
- data->progress.downloaded + data->progress.uploaded;
+ p->speeder[ nowindex ] = p->downloaded + p->uploaded;
/* remember the exact time for this moment */
- data->progress.speeder_time [ nowindex ] = now;
+ p->speeder_time [ nowindex ] = now;
/* advance our speeder_c counter, which is increased every time we get
here and we expect it to never wrap as 2^32 is a lot of seconds! */
- data->progress.speeder_c++;
+ p->speeder_c++;
/* figure out how many index entries of data we have stored in our speeder
array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of
transfer. Imagine, after one second we have filled in two entries,
after two seconds we've filled in three entries etc. */
- countindex = ((data->progress.speeder_c >= CURR_TIME)?
- CURR_TIME:data->progress.speeder_c) - 1;
+ countindex = ((p->speeder_c >= CURR_TIME)? CURR_TIME:p->speeder_c) - 1;
/* first of all, we don't do this if there's no counted seconds yet */
if(countindex) {
int checkindex;
timediff_t span_ms;
+ curl_off_t amount;
/* Get the index position to compare with the 'nowindex' position.
Get the oldest entry possible. While we have less than CURR_TIME
entries, the first entry will remain the oldest. */
- checkindex = (data->progress.speeder_c >= CURR_TIME)?
- data->progress.speeder_c%CURR_TIME:0;
+ checkindex = (p->speeder_c >= CURR_TIME)? p->speeder_c%CURR_TIME:0;
/* Figure out the exact time for the time span */
- span_ms = Curl_timediff(now, data->progress.speeder_time[checkindex]);
+ span_ms = Curl_timediff(now, p->speeder_time[checkindex]);
if(0 == span_ms)
span_ms = 1; /* at least one millisecond MUST have passed */
/* Calculate the average speed the last 'span_ms' milliseconds */
- {
- curl_off_t amount = data->progress.speeder[nowindex]-
- data->progress.speeder[checkindex];
-
- if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */)
- /* the 'amount' value is bigger than would fit in 32 bits if
- multiplied with 1000, so we use the double math for this */
- data->progress.current_speed = (curl_off_t)
- ((double)amount/((double)span_ms/1000.0));
- else
- /* the 'amount' value is small enough to fit within 32 bits even
- when multiplied with 1000 */
- data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms;
- }
+ amount = p->speeder[nowindex]- p->speeder[checkindex];
+
+ if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */)
+ /* the 'amount' value is bigger than would fit in 32 bits if
+ multiplied with 1000, so we use the double math for this */
+ p->current_speed = (curl_off_t)
+ ((double)amount/((double)span_ms/1000.0));
+ else
+ /* the 'amount' value is small enough to fit within 32 bits even
+ when multiplied with 1000 */
+ p->current_speed = amount*CURL_OFF_T_C(1000)/span_ms;
}
else
/* the first second we use the average */
- data->progress.current_speed =
- data->progress.ulspeed + data->progress.dlspeed;
+ p->current_speed = p->ulspeed + p->dlspeed;
} /* Calculations end */
return timetoshow;
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index 55766757a..007d5c50b 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -109,6 +109,7 @@ const struct Curl_handler Curl_handler_rtsp = {
rtsp_disconnect, /* disconnect */
rtsp_rtp_readwrite, /* readwrite */
rtsp_conncheck, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_RTSP, /* defport */
CURLPROTO_RTSP, /* protocol */
CURLPROTO_RTSP, /* family */
@@ -404,8 +405,8 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
/* Referrer */
Curl_safefree(data->state.aptr.ref);
- if(data->change.referer && !Curl_checkheaders(data, "Referer"))
- data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ if(data->state.referer && !Curl_checkheaders(data, "Referer"))
+ data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
else
data->state.aptr.ref = NULL;
@@ -680,7 +681,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
}
}
- if(rtp_dataleft != 0 && rtp[0] == '$') {
+ if(rtp_dataleft && rtp[0] == '$') {
DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft,
*readmore ? "(READMORE)" : ""));
@@ -824,7 +825,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
/* Copy the id substring into a new buffer */
data->set.str[STRING_RTSP_SESSION_ID] = malloc(idlen + 1);
- if(data->set.str[STRING_RTSP_SESSION_ID] == NULL)
+ if(!data->set.str[STRING_RTSP_SESSION_ID])
return CURLE_OUT_OF_MEMORY;
memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen);
(data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
diff --git a/Utilities/cmcurl/lib/select.c b/Utilities/cmcurl/lib/select.c
index 44fe22924..84d0b8ff3 100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@ -442,7 +442,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
if(ufds[i].events & POLLPRI)
ufds[i].revents |= POLLPRI;
}
- if(ufds[i].revents != 0)
+ if(ufds[i].revents)
r++;
}
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index b3c7fe33d..e41bb805f 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -65,7 +65,7 @@ static size_t convert_lineends(struct Curl_easy *data,
char *inPtr, *outPtr;
/* sanity check */
- if((startPtr == NULL) || (size < 1)) {
+ if(!startPtr || (size < 1)) {
return size;
}
@@ -309,6 +309,18 @@ CURLcode Curl_write(struct Curl_easy *data,
conn = data->conn;
num = (sockfd == conn->sock[SECONDARYSOCKET]);
+#ifdef CURLDEBUG
+ {
+ /* Allow debug builds to override this logic to force short sends
+ */
+ char *p = getenv("CURL_SMALLSENDS");
+ if(p) {
+ size_t altsize = (size_t)strtoul(p, NULL, 10);
+ if(altsize)
+ len = CURLMIN(len, altsize);
+ }
+ }
+#endif
bytes_written = conn->send[num](data, num, mem, len, &result);
*written = bytes_written;
@@ -498,9 +510,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
/* store this information in the state struct for later use */
Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER);
s->tempwrite[i].type = type;
-
- if(newtype)
- s->tempcount++;
+ s->tempcount++;
}
if(Curl_dyn_addn(&s->tempwrite[i].b, (unsigned char *)ptr, len))
@@ -606,7 +616,7 @@ static CURLcode chop_write(struct Curl_easy *data,
/* Curl_client_write() sends data to the write callback(s)
The bit pattern defines to what "streams" to write to. Body and/or header.
- The defines are in sendf.h of course.
+ The defines are in sendf.h of course. "len" is not allowed to be 0.
If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
local character encoding. This is a problem and should be changed in
@@ -618,9 +628,8 @@ CURLcode Curl_client_write(struct Curl_easy *data,
size_t len)
{
struct connectdata *conn = data->conn;
- if(0 == len)
- len = strlen(ptr);
+ DEBUGASSERT(len);
DEBUGASSERT(type <= 3);
/* FTP data may need conversion. */
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index ce73a34a7..fb8b86d47 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -177,7 +177,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
- result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -190,7 +190,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_TLS13_CIPHERS:
if(Curl_ssl_tls13_ciphersuites()) {
/* set preferred list of TLS 1.3 cipher suites */
- result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST],
va_arg(param, char *));
}
else
@@ -426,6 +426,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
version_max = C_SSLVERSION_MAX_VALUE(arg);
if(version < CURL_SSLVERSION_DEFAULT ||
+ version == CURL_SSLVERSION_SSLv2 ||
+ version == CURL_SSLVERSION_SSLv3 ||
version >= CURL_SSLVERSION_LAST ||
version_max < CURL_SSLVERSION_MAX_NONE ||
version_max >= CURL_SSLVERSION_MAX_LAST)
@@ -653,8 +655,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.httpauth = CURLAUTH_AWS_SIGV4;
break;
-#endif /* CURL_DISABLE_HTTP */
-
case CURLOPT_MIMEPOST:
/*
* Set to make us do MIME/form POST
@@ -671,13 +671,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String to set in the HTTP Referer: field.
*/
- if(data->change.referer_alloc) {
- Curl_safefree(data->change.referer);
- data->change.referer_alloc = FALSE;
+ if(data->state.referer_alloc) {
+ Curl_safefree(data->state.referer);
+ data->state.referer_alloc = FALSE;
}
result = Curl_setstropt(&data->set.str[STRING_SET_REFERER],
va_arg(param, char *));
- data->change.referer = data->set.str[STRING_SET_REFERER];
+ data->state.referer = data->set.str[STRING_SET_REFERER];
break;
case CURLOPT_USERAGENT:
@@ -695,7 +695,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.headers = va_arg(param, struct curl_slist *);
break;
-#ifndef CURL_DISABLE_HTTP
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXYHEADER:
/*
@@ -747,13 +746,27 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
return CURLE_BAD_FUNCTION_ARGUMENT;
/* append the cookie file name to the list of file names, and deal with
them later */
- cl = curl_slist_append(data->change.cookielist, argptr);
+ cl = curl_slist_append(data->state.cookielist, argptr);
if(!cl) {
- curl_slist_free_all(data->change.cookielist);
- data->change.cookielist = NULL;
+ curl_slist_free_all(data->state.cookielist);
+ data->state.cookielist = NULL;
return CURLE_OUT_OF_MEMORY;
}
- data->change.cookielist = cl; /* store the list for later use */
+ data->state.cookielist = cl; /* store the list for later use */
+ }
+ else {
+ /* clear the list of cookie files */
+ curl_slist_free_all(data->state.cookielist);
+ data->state.cookielist = NULL;
+
+ if(!data->share || !data->share->cookies) {
+ /* throw away all existing cookies if this isn't a shared cookie
+ container */
+ Curl_cookie_clearall(data->cookies);
+ Curl_cookie_cleanup(data->cookies);
+ }
+ /* disable the cookie engine */
+ data->cookies = NULL;
}
break;
@@ -800,7 +813,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_COOKIELIST:
argptr = va_arg(param, char *);
- if(argptr == NULL)
+ if(!argptr)
break;
if(strcasecompare(argptr, "ALL")) {
@@ -891,7 +904,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
if(arg == CURL_HTTP_VERSION_NONE)
arg = CURL_HTTP_VERSION_2TLS;
#endif
- data->set.httpversion = arg;
+ data->set.httpwant = (unsigned char)arg;
break;
case CURLOPT_EXPECT_100_TIMEOUT_MS:
@@ -909,7 +922,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, unsigned long);
if(arg > 1L)
return CURLE_BAD_FUNCTION_ARGUMENT;
+#ifdef USE_HYPER
+ /* Hyper does not support HTTP/0.9 */
+ if(arg)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#else
data->set.http09_allowed = arg ? TRUE : FALSE;
+#endif
break;
#endif /* CURL_DISABLE_HTTP */
@@ -1160,7 +1179,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* An option that changes the command to one that asks for a list only, no
* file info details. Used for FTP, POP3 and SFTP.
*/
- data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_APPEND:
@@ -1168,7 +1187,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* We want to upload and append to an existing file. Used for FTP and
* SFTP.
*/
- data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.remote_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
#ifndef CURL_DISABLE_FTP
@@ -1335,14 +1354,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* The URL to fetch.
*/
- if(data->change.url_alloc) {
+ if(data->state.url_alloc) {
/* the already set URL is allocated, free it first! */
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
+ Curl_safefree(data->state.url);
+ data->state.url_alloc = FALSE;
}
result = Curl_setstropt(&data->set.str[STRING_SET_URL],
va_arg(param, char *));
- data->change.url = data->set.str[STRING_SET_URL];
+ data->state.url = data->set.str[STRING_SET_URL];
break;
case CURLOPT_PORT:
/*
@@ -1416,7 +1435,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_setstropt(&data->set.str[STRING_USERNAME],
va_arg(param, char *));
break;
-
case CURLOPT_PASSWORD:
/*
* authentication password to use in the operation
@@ -1474,7 +1492,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* that aren't actually in use right now will be pruned immediately.
*/
data->set.resolve = va_arg(param, struct curl_slist *);
- data->change.resolve = data->set.resolve;
+ data->state.resolve = data->set.resolve;
break;
case CURLOPT_PROGRESSFUNCTION:
/*
@@ -1666,14 +1684,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds file name of the SSL certificate to use
*/
- result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_CERT],
va_arg(param, char *));
break;
case CURLOPT_SSLCERT_BLOB:
/*
* Blob that holds file name of the SSL certificate to use
*/
- result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_ORIG],
+ result = Curl_setblobopt(&data->set.blobs[BLOB_CERT],
va_arg(param, struct curl_blob *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1696,7 +1714,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds file type of the SSL certificate to use
*/
- result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1712,14 +1730,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds file name of the SSL key to use
*/
- result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_KEY],
va_arg(param, char *));
break;
case CURLOPT_SSLKEY_BLOB:
/*
* Blob that holds file name of the SSL key to use
*/
- result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_ORIG],
+ result = Curl_setblobopt(&data->set.blobs[BLOB_KEY],
va_arg(param, struct curl_blob *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1742,7 +1760,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds file type of the SSL key to use
*/
- result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1758,7 +1776,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds the SSL or SSH private key password.
*/
- result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1852,6 +1870,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.ssl.primary.verifypeer;
}
break;
+ case CURLOPT_DOH_SSL_VERIFYPEER:
+ /*
+ * Enable peer SSL verifying for DOH.
+ */
+ data->set.doh_verifypeer = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_SSL_VERIFYPEER:
/*
@@ -1884,6 +1909,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.ssl.primary.verifyhost;
}
break;
+ case CURLOPT_DOH_SSL_VERIFYHOST:
+ /*
+ * Enable verification of the host name in the peer certificate for DOH
+ */
+ arg = va_arg(param, long);
+
+ /* Treat both 1 and 2 as TRUE */
+ data->set.doh_verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
+ break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_SSL_VERIFYHOST:
/*
@@ -1919,6 +1953,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.ssl.primary.verifystatus;
}
break;
+ case CURLOPT_DOH_SSL_VERIFYSTATUS:
+ /*
+ * Enable certificate status verifying for DOH.
+ */
+ if(!Curl_ssl_cert_status_request()) {
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ }
+
+ data->set.doh_verifystatus = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
case CURLOPT_SSL_CTX_FUNCTION:
/*
* Set a SSL_CTX callback
@@ -1967,7 +2013,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
- result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
va_arg(param, char *));
else
#endif
@@ -1992,9 +2038,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Set CA info for SSL connection. Specify file name of the CA certificate
*/
- result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE],
va_arg(param, char *));
break;
+ case CURLOPT_CAINFO_BLOB:
+ /*
+ * Blob that holds CA info for SSL connection.
+ * Specify entire PEM of the CA certificate
+ */
+#ifdef USE_SSL
+ if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
+ result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
+ va_arg(param, struct curl_blob *));
+ else
+#endif
+ return CURLE_NOT_BUILT_IN;
+
+ break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_CAINFO:
/*
@@ -2004,6 +2064,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
va_arg(param, char *));
break;
+ case CURLOPT_PROXY_CAINFO_BLOB:
+ /*
+ * Blob that holds CA info for SSL connection proxy.
+ * Specify entire PEM of the CA certificate
+ */
+#ifdef USE_SSL
+ if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
+ result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
+ va_arg(param, struct curl_blob *));
+ else
+#endif
+ return CURLE_NOT_BUILT_IN;
+ break;
#endif
case CURLOPT_CAPATH:
/*
@@ -2013,7 +2086,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_CA_PATH)
/* This does not work on windows. */
- result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH],
va_arg(param, char *));
else
#endif
@@ -2040,7 +2113,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set CRL file info for SSL connection. Specify file name of the CRL
* to check certificates revocation
*/
- result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -2058,14 +2131,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set Issuer certificate file
* to check certificates issuer
*/
- result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
va_arg(param, char *));
break;
case CURLOPT_ISSUERCERT_BLOB:
/*
* Blob that holds Issuer certificate to check certificates issuer
*/
- result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG],
+ result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT],
va_arg(param, struct curl_blob *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -2125,7 +2198,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
else if(arg < UPLOADBUFFER_MIN)
arg = UPLOADBUFFER_MIN;
- data->set.upload_buffer_size = arg;
+ data->set.upload_buffer_size = (unsigned int)arg;
Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */
break;
@@ -2238,24 +2311,27 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_SSL_OPTIONS:
arg = va_arg(param, long);
- data->set.ssl.enable_beast =
- (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
+ data->set.ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
+ data->set.ssl.auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
+ /* If a setting is added here it should also be added in dohprobe()
+ which sets its own CURLOPT_SSL_OPTIONS based on these settings. */
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_SSL_OPTIONS:
arg = va_arg(param, long);
- data->set.proxy_ssl.enable_beast =
- (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
+ data->set.proxy_ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
- data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
data->set.proxy_ssl.revoke_best_effort =
!!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
+ data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
+ data->set.proxy_ssl.auto_client_cert =
+ !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
break;
#endif
@@ -2662,9 +2738,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
#ifdef USE_TLS_SRP
case CURLOPT_TLSAUTH_USERNAME:
- result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+ if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
case CURLOPT_PROXY_TLSAUTH_USERNAME:
@@ -2677,9 +2753,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
break;
case CURLOPT_TLSAUTH_PASSWORD:
- result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+ if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
case CURLOPT_PROXY_TLSAUTH_PASSWORD:
@@ -2863,7 +2939,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.trailer_data = va_arg(param, void *);
#endif
break;
-#ifdef USE_HSTS
+#ifndef CURL_DISABLE_HSTS
case CURLOPT_HSTSREADFUNCTION:
data->set.hsts_read = va_arg(param, curl_hstsread_callback);
break;
diff --git a/Utilities/cmcurl/lib/setup-vms.h b/Utilities/cmcurl/lib/setup-vms.h
index ba75dc295..a6710d907 100644
--- a/Utilities/cmcurl/lib/setup-vms.h
+++ b/Utilities/cmcurl/lib/setup-vms.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -87,7 +87,7 @@ static char *vms_translate_path(const char *path)
/* See if the result is in VMS format, if not, we are done */
/* Assume that this is a PATH, not just some data */
test_str = strpbrk(path, ":[<^");
- if(test_str == NULL) {
+ if(!test_str) {
return (char *)path;
}
@@ -119,7 +119,7 @@ static char *vms_getenv(const char *envvar)
/* first use the DECC getenv() function */
result = decc$getenv(envvar);
- if(result == NULL) {
+ if(!result) {
return result;
}
@@ -154,7 +154,7 @@ static struct passwd *vms_getpwuid(uid_t uid)
#endif
my_passwd = decc_getpwuid(uid);
- if(my_passwd == NULL) {
+ if(!my_passwd) {
return my_passwd;
}
diff --git a/Utilities/cmcurl/lib/sha256.c b/Utilities/cmcurl/lib/sha256.c
index d91511791..c34f97e8f 100644
--- a/Utilities/cmcurl/lib/sha256.c
+++ b/Utilities/cmcurl/lib/sha256.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2017, Florin Petriuc, <petriuc.florin@gmail.com>
- * Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018 - 2021, 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
@@ -50,11 +50,10 @@
/* Please keep the SSL backend-specific #if branches in this order:
*
* 1. USE_OPENSSL
- * 2. USE_GNUTLS_NETTLE
- * 3. USE_GNUTLS
- * 4. USE_MBEDTLS
- * 5. USE_COMMON_CRYPTO
- * 6. USE_WIN32_CRYPTO
+ * 2. USE_GNUTLS
+ * 3. USE_MBEDTLS
+ * 4. USE_COMMON_CRYPTO
+ * 5. USE_WIN32_CRYPTO
*
* This ensures that the same SSL branch gets activated throughout this source
* file even if multiple backends are enabled at the same time.
@@ -65,7 +64,7 @@
/* When OpenSSL is available we use the SHA256-function from OpenSSL */
#include <openssl/sha.h>
-#elif defined(USE_GNUTLS_NETTLE)
+#elif defined(USE_GNUTLS)
#include <nettle/sha.h>
@@ -93,35 +92,6 @@ static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
sha256_digest(ctx, SHA256_DIGEST_SIZE, digest);
}
-#elif defined(USE_GNUTLS)
-
-#include <gcrypt.h>
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
-typedef gcry_md_hd_t SHA256_CTX;
-
-static void SHA256_Init(SHA256_CTX *ctx)
-{
- gcry_md_open(ctx, GCRY_MD_SHA256, 0);
-}
-
-static void SHA256_Update(SHA256_CTX *ctx,
- const unsigned char *data,
- unsigned int length)
-{
- gcry_md_write(*ctx, data, length);
-}
-
-static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
-{
- memcpy(digest, gcry_md_read(*ctx, 0), SHA256_DIGEST_LENGTH);
- gcry_md_close(*ctx);
-}
-
#elif defined(USE_MBEDTLS)
#include <mbedtls/sha256.h>
diff --git a/Utilities/cmcurl/lib/share.c b/Utilities/cmcurl/lib/share.c
index 4f1804dbd..9c43c8f70 100644
--- a/Utilities/cmcurl/lib/share.c
+++ b/Utilities/cmcurl/lib/share.c
@@ -235,7 +235,7 @@ Curl_share_lock(struct Curl_easy *data, curl_lock_data type,
{
struct Curl_share *share = data->share;
- if(share == NULL)
+ if(!share)
return CURLSHE_INVALID;
if(share->specifier & (1<<type)) {
@@ -252,7 +252,7 @@ Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
{
struct Curl_share *share = data->share;
- if(share == NULL)
+ if(!share)
return CURLSHE_INVALID;
if(share->specifier & (1<<type)) {
diff --git a/Utilities/cmcurl/lib/sigpipe.h b/Utilities/cmcurl/lib/sigpipe.h
index 430cfc648..d6ec5fca3 100644
--- a/Utilities/cmcurl/lib/sigpipe.h
+++ b/Utilities/cmcurl/lib/sigpipe.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -24,7 +24,7 @@
#include "curl_setup.h"
#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && \
- (defined(USE_OPENSSL) || defined(USE_MBEDTLS))
+ (defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_WOLFSSL))
#include <signal.h>
struct sigpipe_ignore {
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index dd4e4fdbf..39facb267 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
- (CURL_SIZEOF_CURL_OFF_T > 4)
+ (SIZEOF_CURL_OFF_T > 4)
#define BUILDING_CURL_SMB_C
@@ -88,6 +88,7 @@ const struct Curl_handler Curl_handler_smb = {
smb_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_SMB, /* defport */
CURLPROTO_SMB, /* protocol */
CURLPROTO_SMB, /* family */
@@ -114,6 +115,7 @@ const struct Curl_handler Curl_handler_smbs = {
smb_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_SMBS, /* defport */
CURLPROTO_SMBS, /* protocol */
CURLPROTO_SMB, /* family */
@@ -627,9 +629,8 @@ static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
/* Check if there is data in the transfer buffer */
if(!smbc->send_size && smbc->upload_size) {
- size_t nread = smbc->upload_size > data->set.upload_buffer_size ?
- data->set.upload_buffer_size :
- smbc->upload_size;
+ size_t nread = smbc->upload_size > (size_t)data->set.upload_buffer_size ?
+ (size_t)data->set.upload_buffer_size : smbc->upload_size;
data->req.upload_fromhere = data->state.ulbuf;
result = Curl_fillreadbuffer(data, nread, &nread);
if(result && result != CURLE_AGAIN)
@@ -1022,4 +1023,4 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data,
}
#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE &&
- CURL_SIZEOF_CURL_OFF_T > 4 */
+ SIZEOF_CURL_OFF_T > 4 */
diff --git a/Utilities/cmcurl/lib/smb.h b/Utilities/cmcurl/lib/smb.h
index 907cf0c8e..0e3c2ec11 100644
--- a/Utilities/cmcurl/lib/smb.h
+++ b/Utilities/cmcurl/lib/smb.h
@@ -8,7 +8,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018 - 2021, 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
@@ -244,12 +244,12 @@ struct smb_tree_disconnect {
#endif /* BUILDING_CURL_SMB_C */
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
- (CURL_SIZEOF_CURL_OFF_T > 4)
+ (SIZEOF_CURL_OFF_T > 4)
extern const struct Curl_handler Curl_handler_smb;
extern const struct Curl_handler Curl_handler_smbs;
#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE &&
- CURL_SIZEOF_CURL_OFF_T > 4 */
+ SIZEOF_CURL_OFF_T > 4 */
#endif /* HEADER_CURL_SMB_H */
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index 1fc880065..feffc05bc 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_smtp = {
smtp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_SMTP, /* defport */
CURLPROTO_SMTP, /* protocol */
CURLPROTO_SMTP, /* family */
@@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_smtps = {
smtp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_SMTPS, /* defport */
CURLPROTO_SMTPS, /* protocol */
CURLPROTO_SMTP, /* family */
@@ -894,7 +896,7 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
for(;;) {
size_t llen;
size_t wordlen;
- unsigned int mechbit;
+ unsigned short mechbit;
while(len &&
(*line == ' ' || *line == '\t' ||
@@ -1433,7 +1435,7 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
}
/* Clear the transfer mode for the next request */
- smtp->transfer = FTPTRANSFER_BODY;
+ smtp->transfer = PPTRANSFER_BODY;
return result;
}
@@ -1457,7 +1459,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
if(data->set.opt_no_body) {
/* Requested no body means no transfer */
- smtp->transfer = FTPTRANSFER_INFO;
+ smtp->transfer = PPTRANSFER_INFO;
}
*dophase_done = FALSE; /* not done yet */
@@ -1564,7 +1566,7 @@ static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected)
(void)connected;
- if(smtp->transfer != FTPTRANSFER_BODY)
+ if(smtp->transfer != PPTRANSFER_BODY)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
@@ -1821,7 +1823,7 @@ CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread)
return CURLE_OUT_OF_MEMORY;
}
}
- DEBUGASSERT(data->set.upload_buffer_size >= (size_t)nread);
+ DEBUGASSERT((size_t)data->set.upload_buffer_size >= (size_t)nread);
/* Have we already sent part of the EOB? */
eob_sent = smtp->eob;
diff --git a/Utilities/cmcurl/lib/socketpair.h b/Utilities/cmcurl/lib/socketpair.h
index 033a235aa..cdcc0b921 100644
--- a/Utilities/cmcurl/lib/socketpair.h
+++ b/Utilities/cmcurl/lib/socketpair.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2021, 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
@@ -30,7 +30,4 @@ int Curl_socketpair(int domain, int type, int protocol,
#define Curl_socketpair(a,b,c,d) socketpair(a,b,c,d)
#endif
-/* Defined here to allow specific build configs to disable it completely */
-#define USE_SOCKETPAIR 1
-
#endif /* HEADER_CURL_SOCKETPAIR_H */
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index d1c2a2ed1..5cde4a46a 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.c
@@ -426,7 +426,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
*/
/* wrong version ? */
- if(socksreq[0] != 0) {
+ if(socksreq[0]) {
failf(data,
"SOCKS4 reply has wrong version, version should be 0.");
return CURLPX_BAD_VERSION;
@@ -742,7 +742,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
return CURLPX_OK;
}
/* ignore the first (VER) byte */
- else if(socksreq[1] != 0) { /* status */
+ else if(socksreq[1]) { /* status */
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
socksreq[0], socksreq[1]);
return CURLPX_USER_REJECTED;
@@ -927,7 +927,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
"SOCKS5 reply has wrong version, version should be 5.");
return CURLPX_BAD_VERSION;
}
- else if(socksreq[1] != 0) { /* Anything besides 0 is an error */
+ else if(socksreq[1]) { /* Anything besides 0 is an error */
CURLproxycode rc = CURLPX_REPLY_UNASSIGNED;
int code = socksreq[1];
failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
diff --git a/Utilities/cmcurl/lib/socks_gssapi.c b/Utilities/cmcurl/lib/socks_gssapi.c
index 3ab786d0b..10b942a98 100644
--- a/Utilities/cmcurl/lib/socks_gssapi.c
+++ b/Utilities/cmcurl/lib/socks_gssapi.c
@@ -195,7 +195,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- if(gss_send_token.length != 0) {
+ if(gss_send_token.length) {
socksreq[0] = 1; /* GSS-API subnegotiation version */
socksreq[1] = 1; /* authentication message type */
us_length = htons((short)gss_send_token.length);
diff --git a/Utilities/cmcurl/lib/socks_sspi.c b/Utilities/cmcurl/lib/socks_sspi.c
index b343538f0..813c6be57 100644
--- a/Utilities/cmcurl/lib/socks_sspi.c
+++ b/Utilities/cmcurl/lib/socks_sspi.c
@@ -198,7 +198,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- if(sspi_send_token.cbBuffer != 0) {
+ if(sspi_send_token.cbBuffer) {
socksreq[0] = 1; /* GSS-API subnegotiation version */
socksreq[1] = 1; /* authentication message type */
us_length = htons((short)sspi_send_token.cbBuffer);
diff --git a/Utilities/cmcurl/lib/splay.c b/Utilities/cmcurl/lib/splay.c
index 98baf5d87..a94e2c85e 100644
--- a/Utilities/cmcurl/lib/splay.c
+++ b/Utilities/cmcurl/lib/splay.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1997 - 2021, 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
@@ -42,7 +42,7 @@ struct Curl_tree *Curl_splay(struct curltime i,
{
struct Curl_tree N, *l, *r, *y;
- if(t == NULL)
+ if(!t)
return t;
N.smaller = N.larger = NULL;
l = r = &N;
@@ -50,14 +50,14 @@ struct Curl_tree *Curl_splay(struct curltime i,
for(;;) {
long comp = compare(i, t->key);
if(comp < 0) {
- if(t->smaller == NULL)
+ if(!t->smaller)
break;
if(compare(i, t->smaller->key) < 0) {
y = t->smaller; /* rotate smaller */
t->smaller = y->larger;
y->larger = t;
t = y;
- if(t->smaller == NULL)
+ if(!t->smaller)
break;
}
r->smaller = t; /* link smaller */
@@ -65,14 +65,14 @@ struct Curl_tree *Curl_splay(struct curltime i,
t = t->smaller;
}
else if(comp > 0) {
- if(t->larger == NULL)
+ if(!t->larger)
break;
if(compare(i, t->larger->key) > 0) {
y = t->larger; /* rotate larger */
t->larger = y->smaller;
y->smaller = t;
t = y;
- if(t->larger == NULL)
+ if(!t->larger)
break;
}
l->larger = t; /* link larger */
@@ -104,7 +104,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
(time_t)-1, (unsigned int)-1
}; /* will *NEVER* appear */
- if(node == NULL)
+ if(!node)
return t;
if(t != NULL) {
@@ -125,7 +125,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
}
}
- if(t == NULL) {
+ if(!t) {
node->smaller = node->larger = NULL;
}
else if(compare(i, t->key) < 0) {
@@ -262,7 +262,7 @@ int Curl_splayremove(struct Curl_tree *t,
}
else {
/* Remove the root node */
- if(t->smaller == NULL)
+ if(!t->smaller)
x = t->larger;
else {
x = Curl_splay(removenode->key, t->smaller);
diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index 3862aabd6..5298a0d76 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -320,9 +320,12 @@ curl_easy_strerror(CURLcode error)
case CURLE_QUIC_CONNECT_ERROR:
return "QUIC connection error";
- case CURLE_PROXY:
+ case CURLE_PROXY:
return "proxy handshake error";
+ case CURLE_SSL_CLIENTCERT:
+ return "SSL Client Certificate required";
+
/* error codes not used by current libcurl */
case CURLE_OBSOLETE20:
case CURLE_OBSOLETE24:
diff --git a/Utilities/cmcurl/lib/system_win32.c b/Utilities/cmcurl/lib/system_win32.c
index 2132f43ef..2939fd0d7 100644
--- a/Utilities/cmcurl/lib/system_win32.c
+++ b/Utilities/cmcurl/lib/system_win32.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2016 - 2021, 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
@@ -58,7 +58,7 @@ CURLcode Curl_win32_init(long flags)
wVersionRequested = MAKEWORD(2, 2);
res = WSAStartup(wVersionRequested, &wsaData);
- if(res != 0)
+ if(res)
/* Tell the user that we couldn't find a usable */
/* winsock.dll. */
return CURLE_FAILED_INIT;
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index f96a4cb4c..fdd137fb0 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -185,6 +185,7 @@ const struct Curl_handler Curl_handler_telnet = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_TELNET, /* defport */
CURLPROTO_TELNET, /* protocol */
CURLPROTO_TELNET, /* family */
@@ -921,7 +922,7 @@ static void suboption(struct Curl_easy *data)
size_t tmplen = (strlen(v->data) + 1);
/* Add the variable only if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
- if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
+ if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) {
msnprintf((char *)&temp[len], sizeof(temp) - len,
"%c%s%c%s", CURL_NEW_ENV_VAR, varname,
CURL_NEW_ENV_VALUE, varval);
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index 3f1d1b51b..11150af36 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -129,8 +129,6 @@ struct tftp_state_data {
int retries;
int retry_time;
int retry_max;
- time_t start_time;
- time_t max_time;
time_t rx_time;
struct Curl_sockaddr_storage local_addr;
struct Curl_sockaddr_storage remote_addr;
@@ -184,6 +182,7 @@ const struct Curl_handler Curl_handler_tftp = {
tftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_TFTP, /* defport */
CURLPROTO_TFTP, /* protocol */
CURLPROTO_TFTP, /* family */
@@ -206,8 +205,6 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
timediff_t timeout_ms;
bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
- time(&state->start_time);
-
/* Compute drop-dead time */
timeout_ms = Curl_timeleft(state->data, NULL, start);
@@ -217,41 +214,17 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
return CURLE_OPERATION_TIMEDOUT;
}
- if(start) {
-
+ if(timeout_ms > 0)
maxtime = (time_t)(timeout_ms + 500) / 1000;
- state->max_time = state->start_time + maxtime;
-
- /* Set per-block timeout to total */
- timeout = maxtime;
-
- /* Average restart after 5 seconds */
- state->retry_max = (int)timeout/5;
-
- if(state->retry_max < 1)
- /* avoid division by zero below */
- state->retry_max = 1;
-
- /* Compute the re-start interval to suit the timeout */
- state->retry_time = (int)timeout/state->retry_max;
- if(state->retry_time<1)
- state->retry_time = 1;
-
- }
- else {
- if(timeout_ms > 0)
- maxtime = (time_t)(timeout_ms + 500) / 1000;
- else
- maxtime = 3600;
+ else
+ maxtime = 3600; /* use for calculating block timeouts */
- state->max_time = state->start_time + maxtime;
+ /* Set per-block timeout to total */
+ timeout = maxtime;
- /* Set per-block timeout to total */
- timeout = maxtime;
+ /* Average reposting an ACK after 5 seconds */
+ state->retry_max = (int)timeout/5;
- /* Average reposting an ACK after 5 seconds */
- state->retry_max = (int)timeout/5;
- }
/* But bound the total number */
if(state->retry_max<3)
state->retry_max = 3;
@@ -265,9 +238,9 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
state->retry_time = 1;
infof(state->data,
- "set timeouts for state %d; Total %ld, retry %d maxtry %d\n",
- (int)state->state, (long)(state->max_time-state->start_time),
- state->retry_time, state->retry_max);
+ "set timeouts for state %d; Total % " CURL_FORMAT_CURL_OFF_T
+ ", retry %d maxtry %d\n",
+ (int)state->state, timeout_ms, state->retry_time, state->retry_max);
/* init RX time */
time(&state->rx_time);
@@ -347,7 +320,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
const char *option, *value;
tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value);
- if(tmp == NULL) {
+ if(!tmp) {
failf(data, "Malformed ACK packet, rejecting");
return CURLE_TFTP_ILLEGAL;
}
@@ -460,7 +433,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
CURLcode result = CURLE_OK;
/* Set ascii mode if -B flag was used */
- if(data->set.prefer_ascii)
+ if(data->state.prefer_ascii)
mode = "netascii";
switch(event) {
@@ -804,7 +777,7 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
return result;
state->sbytes += (int)cb;
state->data->req.upload_fromhere += cb;
- } while(state->sbytes < state->blksize && cb != 0);
+ } while(state->sbytes < state->blksize && cb);
sbytes = sendto(state->sockfd, (void *) state->spacket.data,
4 + state->sbytes, SEND_4TH_ARG,
@@ -1215,33 +1188,32 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
* Check if timeouts have been reached
*
**********************************************************/
-static long tftp_state_timeout(struct Curl_easy *data, tftp_event_t *event)
+static timediff_t tftp_state_timeout(struct Curl_easy *data,
+ tftp_event_t *event)
{
time_t current;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
+ timediff_t timeout_ms;
if(event)
*event = TFTP_EVENT_NONE;
- time(&current);
- if(current > state->max_time) {
- DEBUGF(infof(data, "timeout: %ld > %ld\n",
- (long)current, (long)state->max_time));
+ timeout_ms = Curl_timeleft(state->data, NULL,
+ (state->state == TFTP_STATE_START));
+ if(timeout_ms < 0) {
state->error = TFTP_ERR_TIMEOUT;
state->state = TFTP_STATE_FIN;
return 0;
}
+ time(&current);
if(current > state->rx_time + state->retry_time) {
if(event)
*event = TFTP_EVENT_TIMEOUT;
time(&state->rx_time); /* update even though we received nothing */
}
- /* there's a typecast below here since 'time_t' may in fact be larger than
- 'long', but we estimate that a 'long' will still be able to hold number
- of seconds even if "only" 32 bit */
- return (long)(state->max_time - current);
+ return timeout_ms;
}
/**********************************************************
@@ -1257,11 +1229,11 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
- long timeout_ms = tftp_state_timeout(data, &event);
+ timediff_t timeout_ms = tftp_state_timeout(data, &event);
*done = FALSE;
- if(timeout_ms <= 0) {
+ if(timeout_ms < 0) {
failf(data, "TFTP response timeout");
return CURLE_OPERATION_TIMEDOUT;
}
@@ -1285,7 +1257,7 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer)));
state->event = TFTP_EVENT_ERROR;
}
- else if(rc != 0) {
+ else if(rc) {
result = tftp_receive_packet(data);
if(result)
return result;
@@ -1420,14 +1392,14 @@ static CURLcode tftp_setup_connection(struct Curl_easy *data,
switch(command) {
case 'A': /* ASCII mode */
case 'N': /* NETASCII mode */
- data->set.prefer_ascii = TRUE;
+ data->state.prefer_ascii = TRUE;
break;
case 'O': /* octet mode */
case 'I': /* binary mode */
default:
/* switch off ASCII */
- data->set.prefer_ascii = FALSE;
+ data->state.prefer_ascii = FALSE;
break;
}
}
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index 8523dad40..ca98fe50e 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -78,14 +78,16 @@ struct curltime Curl_now(void)
** code compiles but fails during run-time if clock_gettime() is
** called on unsupported OS version.
*/
-#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1)
+#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \
+ (HAVE_BUILTIN_AVAILABLE == 1)
bool have_clock_gettime = FALSE;
if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *))
have_clock_gettime = TRUE;
#endif
if(
-#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1)
+#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \
+ (HAVE_BUILTIN_AVAILABLE == 1)
have_clock_gettime &&
#endif
(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) {
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index 2f29b29d8..bca4e548f 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -79,6 +79,7 @@
#include "strcase.h"
#include "urlapi-int.h"
#include "hsts.h"
+#include "setopt.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -98,6 +99,8 @@ char *Curl_checkheaders(const struct Curl_easy *data,
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
+ DEBUGASSERT(thislen);
+ DEBUGASSERT(thisheader[thislen-1] != ':');
for(head = data->set.headers; head; head = head->next) {
if(strncasecompare(head->data, thisheader, thislen) &&
@@ -286,7 +289,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
* <DATA> CRLF
*/
/* On non-ASCII platforms the <DATA> may or may not be
- translated based on set.prefer_ascii while the protocol
+ translated based on state.prefer_ascii while the protocol
portion must always be translated to the network encoding.
To further complicate matters, line end conversion might be
done later on, so we need to prevent CRLFs from becoming
@@ -301,7 +304,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
if(
#ifdef CURL_DO_LINEEND_CONV
- (data->set.prefer_ascii) ||
+ (data->state.prefer_ascii) ||
#endif
(data->set.crlf)) {
/* \n will become \r\n later on */
@@ -348,7 +351,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
{
CURLcode result;
size_t length;
- if(data->set.prefer_ascii)
+ if(data->state.prefer_ascii)
/* translate the protocol and data */
length = nread;
else
@@ -389,7 +392,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
nread += strlen(endofline_network); /* for the added end of line */
}
#ifdef CURL_DOES_CONVERSIONS
- else if((data->set.prefer_ascii) && (!sending_http_headers)) {
+ else if((data->state.prefer_ascii) && (!sending_http_headers)) {
CURLcode result;
result = Curl_convert_to_network(data, data->req.upload_fromhere, nread);
/* Curl_convert_to_network calls failf if unsuccessful */
@@ -494,11 +497,13 @@ static int data_pending(const struct Curl_easy *data)
return Curl_quic_data_pending(data);
#endif
+ if(conn->handler->protocol&PROTO_FAMILY_FTP)
+ return Curl_ssl_data_pending(conn, SECONDARYSOCKET);
+
/* in the case of libssh2, we can never be really sure that we have emptied
its internal buffers so we MUST always try until we get EAGAIN back */
return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
#if defined(USE_NGHTTP2)
- Curl_ssl_data_pending(conn, FIRSTSOCKET) ||
/* For HTTP/2, we may read up everything including response body
with header fields in Curl_http_readwrite_headers. If no
content-length is provided, curl waits for the connection
@@ -506,10 +511,9 @@ static int data_pending(const struct Curl_easy *data)
TRUE. The thing is if we read everything, then http2_recv won't
be called and we cannot signal the HTTP/2 stream has closed. As
a workaround, we return nonzero here to call http2_recv. */
- ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20);
-#else
- Curl_ssl_data_pending(conn, FIRSTSOCKET);
+ ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20) ||
#endif
+ Curl_ssl_data_pending(conn, FIRSTSOCKET);
}
/*
@@ -829,7 +833,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
Make sure that ALL_CONTENT_ENCODINGS contains all the
encodings handled here. */
if(data->set.http_ce_skip || !k->writer_stack) {
- if(!k->ignorebody) {
+ if(!k->ignorebody && nread) {
#ifndef CURL_DISABLE_POP3
if(conn->handler->protocol & PROTO_FAMILY_POP3)
result = Curl_pop3_write(data, k->str, nread);
@@ -839,7 +843,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
nread);
}
}
- else if(!k->ignorebody)
+ else if(!k->ignorebody && nread)
result = Curl_unencode_write(data, k->writer_stack, k->str, nread);
}
k->badheader = HEADER_NORMAL; /* taken care of now */
@@ -1028,7 +1032,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
if((!sending_http_headers) && (
#ifdef CURL_DO_LINEEND_CONV
/* always convert if we're FTPing in ASCII mode */
- (data->set.prefer_ascii) ||
+ (data->state.prefer_ascii) ||
#endif
(data->set.crlf))) {
/* Do we need to allocate a scratch buffer? */
@@ -1391,20 +1395,20 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
{
CURLcode result;
- if(!data->change.url && !data->set.uh) {
+ if(!data->state.url && !data->set.uh) {
/* we can't do anything without URL */
failf(data, "No URL set!");
return CURLE_URL_MALFORMAT;
}
/* since the URL may have been redirected in a previous use of this handle */
- if(data->change.url_alloc) {
+ if(data->state.url_alloc) {
/* the already set URL is allocated, free it first! */
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
+ Curl_safefree(data->state.url);
+ data->state.url_alloc = FALSE;
}
- if(!data->change.url && data->set.uh) {
+ if(!data->state.url && data->set.uh) {
CURLUcode uc;
free(data->set.str[STRING_SET_URL]);
uc = curl_url_get(data->set.uh,
@@ -1415,8 +1419,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
}
}
+ data->state.prefer_ascii = data->set.prefer_ascii;
+ data->state.list_only = data->set.list_only;
data->state.httpreq = data->set.method;
- data->change.url = data->set.str[STRING_SET_URL];
+ data->state.url = data->set.str[STRING_SET_URL];
/* Init the SSL session ID cache here. We do it here since we want to do it
after the *_setopt() calls (that could specify the size of the cache) but
@@ -1426,11 +1432,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
return result;
data->state.wildcardmatch = data->set.wildcard_enabled;
- data->set.followlocation = 0; /* reset the location-follow counter */
+ 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 */
- data->state.httpversion = 0; /* don't assume any particular server version */
-
+ data->state.httpwant = data->set.httpwant;
+ data->state.httpversion = 0;
data->state.authproblem = FALSE;
data->state.authhost.want = data->set.httpauth;
data->state.authproxy.want = data->set.proxyauth;
@@ -1448,11 +1454,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
data->state.infilesize = 0;
/* If there is a list of cookie files to read, do it now! */
- if(data->change.cookielist)
+ if(data->state.cookielist)
Curl_cookie_loadfiles(data);
/* If there is a list of host pairs to deal with */
- if(data->change.resolve)
+ if(data->state.resolve)
result = Curl_loadhostpairs(data);
if(!result) {
@@ -1506,6 +1512,19 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
}
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.user,
+ data->set.str[STRING_USERNAME]);
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.passwd,
+ data->set.str[STRING_PASSWORD]);
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.proxyuser,
+ data->set.str[STRING_PROXYUSERNAME]);
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.proxypasswd,
+ data->set.str[STRING_PROXYPASSWORD]);
+
data->req.headerbytecount = 0;
return result;
}
@@ -1553,7 +1572,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
if(type == FOLLOW_REDIR) {
if((data->set.maxredirs != -1) &&
- (data->set.followlocation >= data->set.maxredirs)) {
+ (data->state.followlocation >= data->set.maxredirs)) {
reachedmax = TRUE;
type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
to URL */
@@ -1562,22 +1581,43 @@ CURLcode Curl_follow(struct Curl_easy *data,
/* mark the next request as a followed location: */
data->state.this_is_a_follow = TRUE;
- data->set.followlocation++; /* count location-followers */
+ data->state.followlocation++; /* count location-followers */
if(data->set.http_auto_referer) {
+ CURLU *u;
+ char *referer = NULL;
+
/* We are asked to automatically set the previous URL as the referer
when we get the next URL. We pick the ->url field, which may or may
not be 100% correct */
- if(data->change.referer_alloc) {
- Curl_safefree(data->change.referer);
- data->change.referer_alloc = FALSE;
+ if(data->state.referer_alloc) {
+ Curl_safefree(data->state.referer);
+ data->state.referer_alloc = FALSE;
}
- data->change.referer = strdup(data->change.url);
- if(!data->change.referer)
+ /* Make a copy of the URL without crenditals and fragment */
+ u = curl_url();
+ if(!u)
+ return CURLE_OUT_OF_MEMORY;
+
+ uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
+ if(!uc)
+ uc = curl_url_get(u, CURLUPART_URL, &referer, 0);
+
+ curl_url_cleanup(u);
+
+ if(uc || !referer)
return CURLE_OUT_OF_MEMORY;
- data->change.referer_alloc = TRUE; /* yes, free this later */
+
+ data->state.referer = referer;
+ data->state.referer_alloc = TRUE; /* yes, free this later */
}
}
}
@@ -1625,13 +1665,13 @@ CURLcode Curl_follow(struct Curl_easy *data,
if(disallowport)
data->state.allow_port = FALSE;
- if(data->change.url_alloc)
- Curl_safefree(data->change.url);
+ if(data->state.url_alloc)
+ Curl_safefree(data->state.url);
- data->change.url = newurl;
- data->change.url_alloc = TRUE;
+ data->state.url = newurl;
+ data->state.url_alloc = TRUE;
- infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
+ infof(data, "Issue another request to this URL: '%s'\n", data->state.url);
/*
* We get here when the HTTP code is 300-399 (and 401). We need to perform
@@ -1792,7 +1832,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
}
infof(data, "Connection died, retrying a fresh connect\
(retry count: %d)\n", data->state.retrycount);
- *url = strdup(data->change.url);
+ *url = strdup(data->state.url);
if(!*url)
return CURLE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index c02d2c201..1ee38af0d 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -234,7 +234,7 @@ static const struct Curl_handler * const protocols[] = {
#endif
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
- (CURL_SIZEOF_CURL_OFF_T > 4)
+ (SIZEOF_CURL_OFF_T > 4)
&Curl_handler_smb,
#ifdef USE_SSL
&Curl_handler_smbs,
@@ -292,6 +292,7 @@ static const struct Curl_handler Curl_handler_dummy = {
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
0, /* defport */
0, /* protocol */
0, /* family */
@@ -312,16 +313,16 @@ void Curl_freeset(struct Curl_easy *data)
Curl_safefree(data->set.blobs[j]);
}
- if(data->change.referer_alloc) {
- Curl_safefree(data->change.referer);
- data->change.referer_alloc = FALSE;
+ if(data->state.referer_alloc) {
+ Curl_safefree(data->state.referer);
+ data->state.referer_alloc = FALSE;
}
- data->change.referer = NULL;
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
+ data->state.referer = NULL;
+ if(data->state.url_alloc) {
+ Curl_safefree(data->state.url);
+ data->state.url_alloc = FALSE;
}
- data->change.url = NULL;
+ data->state.url = NULL;
Curl_mime_cleanpart(&data->set.mimepost);
}
@@ -405,11 +406,11 @@ CURLcode Curl_close(struct Curl_easy **datap)
free(data->req.newurl);
data->req.newurl = NULL;
- if(data->change.referer_alloc) {
- Curl_safefree(data->change.referer);
- data->change.referer_alloc = FALSE;
+ if(data->state.referer_alloc) {
+ Curl_safefree(data->state.referer);
+ data->state.referer_alloc = FALSE;
}
- data->change.referer = NULL;
+ data->state.referer = NULL;
up_free(data);
Curl_safefree(data->state.buffer);
@@ -449,6 +450,10 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->state.aptr.host);
Curl_safefree(data->state.aptr.cookiehost);
Curl_safefree(data->state.aptr.rtsp_transport);
+ Curl_safefree(data->state.aptr.user);
+ Curl_safefree(data->state.aptr.passwd);
+ Curl_safefree(data->state.aptr.proxyuser);
+ Curl_safefree(data->state.aptr.proxypasswd);
#ifndef CURL_DISABLE_DOH
if(data->req.doh) {
@@ -530,6 +535,8 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
* libcurl 7.10 introduced SSL verification *by default*! This needs to be
* switched off unless wanted.
*/
+ set->doh_verifyhost = TRUE;
+ set->doh_verifypeer = TRUE;
set->ssl.primary.verifypeer = TRUE;
set->ssl.primary.verifyhost = TRUE;
#ifdef USE_TLS_SRP
@@ -569,7 +576,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
*/
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
#if defined(CURL_CA_BUNDLE)
- result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
if(result)
return result;
@@ -579,7 +586,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
return result;
#endif
#if defined(CURL_CA_PATH)
- result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
if(result)
return result;
@@ -609,7 +616,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
set->maxage_conn = 118;
set->http09_allowed = FALSE;
- set->httpversion =
+ set->httpwant =
#ifdef USE_NGHTTP2
CURL_HTTP_VERSION_2TLS
#else
@@ -837,7 +844,7 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
dead_connection = TRUE;
/* temporarily attach the connection to this transfer handle for the
- disonnect and shutdown */
+ disconnect and shutdown */
Curl_attach_connnection(data, conn);
if(conn->handler->disconnect)
@@ -887,7 +894,7 @@ static int IsMultiplexingPossible(const struct Curl_easy *handle,
(!conn->bits.protoconnstart || !conn->bits.close)) {
if(Curl_multiplex_wanted(handle->multi) &&
- (handle->set.httpversion >= CURL_HTTP_VERSION_2))
+ (handle->state.httpwant >= CURL_HTTP_VERSION_2))
/* allows HTTP/2 */
avail |= CURLPIPE_MULTIPLEX;
}
@@ -917,14 +924,14 @@ 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://tools.ietf.org/html/rfc3986#section-3.2.1 */
- if((data->user == NULL) != (needle->user == NULL))
+ 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 == NULL) != (needle->passwd == NULL))
+ if(!data->passwd != !needle->passwd)
return FALSE;
/* curl_strequal does a case insentive comparison, so do not use it here! */
if(data->passwd &&
@@ -986,12 +993,12 @@ static bool extract_if_dead(struct connectdata *conn,
/* briefly attach the connection to this transfer for the purpose of
checking it */
Curl_attach_connnection(data, conn);
- conn->data = data; /* find the way back if necessary */
+
state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD);
dead = (state & CONNRESULT_DEAD);
/* detach the connection again */
Curl_detach_connnection(data);
- conn->data = NULL; /* clear it again */
+
}
else {
/* Use the general method for determining the death of a connection */
@@ -1092,13 +1099,13 @@ ConnectionExists(struct Curl_easy *data,
#ifdef USE_NTLM
bool wantNTLMhttp = ((data->state.authhost.want &
- (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
- (needle->handler->protocol & PROTO_FAMILY_HTTP));
+ (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+ (needle->handler->protocol & PROTO_FAMILY_HTTP));
#ifndef CURL_DISABLE_PROXY
bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
- ((data->state.authproxy.want &
- (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
- (needle->handler->protocol & PROTO_FAMILY_HTTP)));
+ ((data->state.authproxy.want &
+ (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+ (needle->handler->protocol & PROTO_FAMILY_HTTP)));
#else
bool wantProxyNTLMhttp = FALSE;
#endif
@@ -1165,6 +1172,12 @@ ConnectionExists(struct Curl_easy *data,
continue;
}
+ if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
+ && data->set.ipver != check->ip_version) {
+ /* skip because the connection is not via the requested IP version */
+ continue;
+ }
+
if(bundle->multiuse == BUNDLE_MULTIPLEX)
multiplexed = CONN_INUSE(check);
@@ -1266,17 +1279,19 @@ ConnectionExists(struct Curl_easy *data,
}
#endif
- DEBUGASSERT(!check->data || GOOD_EASY_HANDLE(check->data));
-
- if(!canmultiplex && check->data)
+ if(!canmultiplex && CONN_INUSE(check))
/* this request can't be multiplexed but the checked connection is
already in use so we skip it */
continue;
- if(check->data && (check->data->multi != needle->data->multi))
- /* this could be subject for multiplex use, but only if they belong to
- * the same multi handle */
- continue;
+ if(CONN_INUSE(check)) {
+ /* Subject for multiplex use if 'checks' belongs to the same multi
+ handle as 'data' is. */
+ struct Curl_llist_element *e = check->easyq.head;
+ struct Curl_easy *entry = e->ptr;
+ if(entry->multi != data->multi)
+ continue;
+ }
if(needle->localdev || needle->localport) {
/* If we are bound to a specific local end (IP+port), we must not
@@ -1307,6 +1322,13 @@ ConnectionExists(struct Curl_easy *data,
}
}
+ /* If multiplexing isn't enabled on the h2 connection and h1 is
+ explicitly requested, handle it: */
+ if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
+ (check->httpversion >= 20) &&
+ (data->state.httpwant < CURL_HTTP_VERSION_2_0))
+ continue;
+
if((needle->handler->flags&PROTOPT_SSL)
#ifndef CURL_DISABLE_PROXY
|| !needle->bits.httpproxy || needle->bits.tunnel_proxy
@@ -1435,7 +1457,7 @@ ConnectionExists(struct Curl_easy *data,
continue;
}
else if(multiplexed >=
- Curl_multi_max_concurrent_streams(needle->data->multi)) {
+ Curl_multi_max_concurrent_streams(data->multi)) {
infof(data, "client side MAX_CONCURRENT_STREAMS reached"
", skip (%zu)\n",
multiplexed);
@@ -1459,7 +1481,6 @@ ConnectionExists(struct Curl_easy *data,
if(chosen) {
/* mark it as used before releasing the lock */
- chosen->data = data; /* own it! */
Curl_attach_connnection(data, chosen);
CONNCACHE_UNLOCK(data);
*usethis = chosen;
@@ -1674,9 +1695,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
/* Store current time to give a baseline to keepalive connection times. */
conn->keepalive = Curl_now();
- conn->data = data; /* Setup the association between this connection
- and the Curl_easy */
-
#ifndef CURL_DISABLE_PROXY
conn->http_proxy.proxytype = data->set.proxytype;
conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
@@ -1699,11 +1717,11 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
}
conn->bits.proxy_user_passwd =
- (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
+ (data->state.aptr.proxyuser) ? TRUE : FALSE;
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
#endif /* CURL_DISABLE_PROXY */
- conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
+ conn->bits.user_passwd = (data->state.aptr.user) ? TRUE : FALSE;
#ifndef CURL_DISABLE_FTP
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
@@ -1896,28 +1914,27 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
- !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) {
- char *url;
- if(data->change.url_alloc)
- free(data->change.url);
- url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
- data->change.url);
+ !Curl_is_absolute_url(data->state.url, NULL, MAX_SCHEME_LEN)) {
+ char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
+ data->state.url);
if(!url)
return CURLE_OUT_OF_MEMORY;
- data->change.url = url;
- data->change.url_alloc = TRUE;
+ if(data->state.url_alloc)
+ free(data->state.url);
+ data->state.url = url;
+ data->state.url_alloc = TRUE;
}
if(!use_set_uh) {
char *newurl;
- uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
+ uc = curl_url_set(uh, CURLUPART_URL, data->state.url,
CURLU_GUESS_SCHEME |
CURLU_NON_SUPPORT_SCHEME |
(data->set.disallow_username_in_url ?
CURLU_DISALLOW_USER : 0) |
(data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
if(uc) {
- DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url));
+ DEBUGF(infof(data, "curl_url_set rejected %s\n", data->state.url));
return Curl_uc_to_curlcode(uc);
}
@@ -1925,10 +1942,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
uc = curl_url_get(uh, CURLUPART_URL, &newurl, 0);
if(uc)
return Curl_uc_to_curlcode(uc);
- if(data->change.url_alloc)
- free(data->change.url);
- data->change.url = newurl;
- data->change.url_alloc = TRUE;
+ if(data->state.url_alloc)
+ free(data->state.url);
+ data->state.url = newurl;
+ data->state.url_alloc = TRUE;
}
uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
@@ -1941,7 +1958,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
-#ifdef USE_HSTS
+#ifndef CURL_DISABLE_HSTS
if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) {
char *url;
@@ -1949,19 +1966,21 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
if(uc)
return Curl_uc_to_curlcode(uc);
- if(data->change.url_alloc)
- Curl_safefree(data->change.url);
+ if(data->state.url_alloc)
+ Curl_safefree(data->state.url);
/* after update, get the updated version */
uc = curl_url_get(uh, CURLUPART_URL, &url, 0);
if(uc)
return Curl_uc_to_curlcode(uc);
uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
- if(uc)
+ if(uc) {
+ free(url);
return Curl_uc_to_curlcode(uc);
- data->change.url = url;
- data->change.url_alloc = TRUE;
+ }
+ data->state.url = url;
+ data->state.url_alloc = TRUE;
infof(data, "Switched from HTTP to HTTPS due to HSTS => %s\n",
- data->change.url);
+ data->state.url);
}
}
#endif
@@ -1970,36 +1989,50 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
if(result)
return result;
- /* 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 */
- uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
- if(!uc) {
- char *decoded;
- result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL,
- conn->handler->flags&PROTOPT_USERPWDCTRL ?
- REJECT_ZERO : REJECT_CTRL);
- if(result)
- return result;
- conn->user = decoded;
- conn->bits.user_passwd = TRUE;
+ /*
+ * User name and password set with their own options override the
+ * credentials possibly set in the URL.
+ */
+ if(!data->state.aptr.user) {
+ /* 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 */
+ uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
+ if(!uc) {
+ char *decoded;
+ result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL,
+ conn->handler->flags&PROTOPT_USERPWDCTRL ?
+ REJECT_ZERO : REJECT_CTRL);
+ if(result)
+ return result;
+ conn->user = decoded;
+ conn->bits.user_passwd = TRUE;
+ result = Curl_setstropt(&data->state.aptr.user, decoded);
+ if(result)
+ return result;
+ }
+ else if(uc != CURLUE_NO_USER)
+ return Curl_uc_to_curlcode(uc);
}
- else if(uc != CURLUE_NO_USER)
- return Curl_uc_to_curlcode(uc);
- uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
- if(!uc) {
- char *decoded;
- result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL,
- conn->handler->flags&PROTOPT_USERPWDCTRL ?
- REJECT_ZERO : REJECT_CTRL);
- if(result)
- return result;
- conn->passwd = decoded;
- conn->bits.user_passwd = TRUE;
+ if(!data->state.aptr.passwd) {
+ uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
+ if(!uc) {
+ char *decoded;
+ result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL,
+ conn->handler->flags&PROTOPT_USERPWDCTRL ?
+ REJECT_ZERO : REJECT_CTRL);
+ if(result)
+ return result;
+ conn->passwd = decoded;
+ conn->bits.user_passwd = TRUE;
+ result = Curl_setstropt(&data->state.aptr.passwd, decoded);
+ if(result)
+ return result;
+ }
+ else if(uc != CURLUE_NO_PASSWORD)
+ return Curl_uc_to_curlcode(uc);
}
- else if(uc != CURLUE_NO_PASSWORD)
- return Curl_uc_to_curlcode(uc);
uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
CURLU_URLDECODE);
@@ -2385,11 +2418,20 @@ static CURLcode parse_proxy(struct Curl_easy *data,
proxyinfo->proxytype = proxytype;
/* Is there a username and password given in this proxy url? */
- curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
- curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE);
+ uc = curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
+ if(uc && (uc != CURLUE_NO_USER))
+ goto error;
+ uc = curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE);
+ if(uc && (uc != CURLUE_NO_PASSWORD))
+ goto error;
+
if(proxyuser || proxypasswd) {
Curl_safefree(proxyinfo->user);
proxyinfo->user = proxyuser;
+ result = Curl_setstropt(&data->state.aptr.proxyuser, proxyuser);
+ proxyuser = NULL;
+ if(result)
+ goto error;
Curl_safefree(proxyinfo->passwd);
if(!proxypasswd) {
proxypasswd = strdup("");
@@ -2399,6 +2441,10 @@ static CURLcode parse_proxy(struct Curl_easy *data,
}
}
proxyinfo->passwd = proxypasswd;
+ result = Curl_setstropt(&data->state.aptr.proxypasswd, proxypasswd);
+ proxypasswd = NULL;
+ if(result)
+ goto error;
conn->bits.proxy_user_passwd = TRUE; /* enable it */
}
@@ -2444,6 +2490,8 @@ static CURLcode parse_proxy(struct Curl_easy *data,
proxyinfo->host.name = host;
error:
+ free(proxyuser);
+ free(proxypasswd);
free(scheme);
curl_url_cleanup(uhp);
return result;
@@ -2455,18 +2503,26 @@ static CURLcode parse_proxy(struct Curl_easy *data,
static CURLcode parse_proxy_auth(struct Curl_easy *data,
struct connectdata *conn)
{
- const char *proxyuser = data->set.str[STRING_PROXYUSERNAME] ?
- data->set.str[STRING_PROXYUSERNAME] : "";
- const char *proxypasswd = data->set.str[STRING_PROXYPASSWORD] ?
- data->set.str[STRING_PROXYPASSWORD] : "";
+ const char *proxyuser = data->state.aptr.proxyuser ?
+ data->state.aptr.proxyuser : "";
+ const char *proxypasswd = data->state.aptr.proxypasswd ?
+ data->state.aptr.proxypasswd : "";
CURLcode result = CURLE_OK;
- if(proxyuser)
+ if(proxyuser) {
result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
REJECT_ZERO);
- if(!result && proxypasswd)
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.proxyuser,
+ conn->http_proxy.user);
+ }
+ if(!result && proxypasswd) {
result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
NULL, REJECT_ZERO);
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.proxypasswd,
+ conn->http_proxy.passwd);
+ }
return result;
}
@@ -2808,44 +2864,19 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
* option or a .netrc file, if applicable.
*/
static CURLcode override_login(struct Curl_easy *data,
- struct connectdata *conn,
- char **userp, char **passwdp, char **optionsp)
+ struct connectdata *conn)
{
- bool user_changed = FALSE;
- bool passwd_changed = FALSE;
CURLUcode uc;
+ char **userp = &conn->user;
+ char **passwdp = &conn->passwd;
+ char **optionsp = &conn->options;
if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
- /* ignore user+password in the URL */
- if(*userp) {
- Curl_safefree(*userp);
- user_changed = TRUE;
- }
- if(*passwdp) {
- Curl_safefree(*passwdp);
- passwd_changed = TRUE;
- }
+ Curl_safefree(*userp);
+ Curl_safefree(*passwdp);
conn->bits.user_passwd = FALSE; /* disable user+password */
}
- if(data->set.str[STRING_USERNAME]) {
- free(*userp);
- *userp = strdup(data->set.str[STRING_USERNAME]);
- if(!*userp)
- return CURLE_OUT_OF_MEMORY;
- conn->bits.user_passwd = TRUE; /* enable user+password */
- user_changed = TRUE;
- }
-
- if(data->set.str[STRING_PASSWORD]) {
- free(*passwdp);
- *passwdp = strdup(data->set.str[STRING_PASSWORD]);
- if(!*passwdp)
- return CURLE_OUT_OF_MEMORY;
- conn->bits.user_passwd = TRUE; /* enable user+password */
- passwd_changed = TRUE;
- }
-
if(data->set.str[STRING_OPTIONS]) {
free(*optionsp);
*optionsp = strdup(data->set.str[STRING_OPTIONS]);
@@ -2854,8 +2885,7 @@ static CURLcode override_login(struct Curl_easy *data,
}
conn->bits.netrc = FALSE;
- if(data->set.use_netrc != CURL_NETRC_IGNORED &&
- (!*userp || !**userp || !*passwdp || !**passwdp)) {
+ if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
bool netrc_user_changed = FALSE;
bool netrc_passwd_changed = FALSE;
int ret;
@@ -2865,8 +2895,8 @@ static CURLcode override_login(struct Curl_easy *data,
&netrc_user_changed, &netrc_passwd_changed,
data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
- infof(data, "Couldn't find host %s in the .netrc file; using defaults\n",
- conn->host.name);
+ infof(data, "Couldn't find host %s in the %s file; using defaults\n",
+ conn->host.name, data->set.str[STRING_NETRC_FILE]);
}
else if(ret < 0) {
return CURLE_OUT_OF_MEMORY;
@@ -2877,29 +2907,44 @@ static CURLcode override_login(struct Curl_easy *data,
different host or similar. */
conn->bits.netrc = TRUE;
conn->bits.user_passwd = TRUE; /* enable user+password */
-
- if(netrc_user_changed) {
- user_changed = TRUE;
- }
- if(netrc_passwd_changed) {
- passwd_changed = TRUE;
- }
}
}
/* for updated strings, we update them in the URL */
- if(user_changed) {
- uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp,
+ if(*userp) {
+ CURLcode 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(passwd_changed) {
- uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp,
- CURLU_URLENCODE);
+
+ if(*passwdp) {
+ CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);
+ if(result)
+ return result;
+ }
+ if(data->state.aptr.passwd) {
+ uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,
+ data->state.aptr.passwd, CURLU_URLENCODE);
if(uc)
return Curl_uc_to_curlcode(uc);
+ if(!*passwdp) {
+ *passwdp = strdup(data->state.aptr.passwd);
+ if(!*passwdp)
+ return CURLE_OUT_OF_MEMORY;
+ }
}
+
return CURLE_OK;
}
@@ -3315,7 +3360,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
result = CURLE_OPERATION_TIMEDOUT;
else if(!hostaddr) {
- failf(data, "Couldn't resolve host '%s'", connhost->dispname);
+ 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 */
}
@@ -3367,7 +3412,7 @@ static void reuse_conn(struct Curl_easy *data,
ip address and port number whenever an outgoing connection is
**established** from the primary socket to a remote address. */
char local_ip[MAX_IPADR_LEN] = "";
- long local_port = -1;
+ 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);
@@ -3380,8 +3425,6 @@ static void reuse_conn(struct Curl_easy *data,
allocated in vain and is targeted for destruction */
Curl_free_primary_ssl_config(&old_conn->ssl_config);
- conn->data = data;
-
/* 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 */
conn->bits.user_passwd = old_conn->bits.user_passwd;
@@ -3469,7 +3512,6 @@ static void reuse_conn(struct Curl_easy *data,
* @param async is set TRUE when an async DNS resolution is pending
* @see Curl_setup_conn()
*
- * *NOTE* this function assigns the conn->data pointer!
*/
static CURLcode create_conn(struct Curl_easy *data,
@@ -3492,7 +3534,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/*************************************************************
* Check input data
*************************************************************/
- if(!data->change.url) {
+ if(!data->state.url) {
result = CURLE_URL_MALFORMAT;
goto out;
}
@@ -3528,7 +3570,7 @@ static CURLcode create_conn(struct Curl_easy *data,
#ifdef USE_UNIX_SOCKETS
if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
- if(conn->unix_domain_socket == NULL) {
+ if(!conn->unix_domain_socket) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
@@ -3560,8 +3602,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/* Check for overridden login details and set them accordingly so they
they are known when protocol->setup_connection is called! */
- result = override_login(data, conn, &conn->user, &conn->passwd,
- &conn->options);
+ result = override_login(data, conn);
if(result)
goto out;
@@ -3693,17 +3734,18 @@ static CURLcode create_conn(struct Curl_easy *data,
that will be freed as part of the Curl_easy struct, but all cloned
copies will be separately allocated.
*/
- data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
- data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
+ data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
+ data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
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_ORIG];
+ data->set.str[STRING_SSL_CIPHER_LIST];
data->set.ssl.primary.cipher_list13 =
- data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
+ data->set.str[STRING_SSL_CIPHER13_LIST];
data->set.ssl.primary.pinned_key =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
- data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
+ data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
#ifndef CURL_DISABLE_PROXY
@@ -3719,6 +3761,8 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.primary.pinned_key =
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
+ data->set.proxy_ssl.primary.ca_info_blob =
+ data->set.blobs[BLOB_CAINFO_PROXY];
data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
@@ -3728,24 +3772,24 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
#endif
- data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
- data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
- data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
- data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
- data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
- data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
- data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
+ data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+ data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
+ data->set.ssl.key = data->set.str[STRING_KEY];
+ data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
+ data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
+ data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
#ifdef USE_TLS_SRP
- data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
- data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
+ data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
+ data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
#endif
#endif
- data->set.ssl.key_blob = data->set.blobs[BLOB_KEY_ORIG];
- data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG];
+ data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
+ data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
&conn->ssl_config)) {
@@ -3952,10 +3996,7 @@ out:
* create_conn() is all done.
*
* Curl_setup_conn() also handles reused connections
- *
- * conn->data MUST already have been setup fine (in create_conn)
*/
-
CURLcode Curl_setup_conn(struct Curl_easy *data,
bool *protocol_done)
{
diff --git a/Utilities/cmcurl/lib/urlapi.c b/Utilities/cmcurl/lib/urlapi.c
index e3a788221..6483208ec 100644
--- a/Utilities/cmcurl/lib/urlapi.c
+++ b/Utilities/cmcurl/lib/urlapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -667,6 +667,94 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
#define HOSTNAME_END(x) (((x) == '/') || ((x) == '?') || ((x) == '#'))
+/*
+ * Handle partial IPv4 numerical addresses and different bases, like
+ * '16843009', '0x7f', '0x7f.1' '0177.1.1.1' etc.
+ *
+ * If the given input string is syntactically wrong or any part for example is
+ * too big, this function returns FALSE and doesn't create any output.
+ *
+ * Output the "normalized" version of that input string in plain quad decimal
+ * integers and return TRUE.
+ */
+static bool ipv4_normalize(const char *hostname, char *outp, size_t olen)
+{
+ bool done = FALSE;
+ int n = 0;
+ const char *c = hostname;
+ unsigned long parts[4] = {0, 0, 0, 0};
+
+ while(!done) {
+ char *endp;
+ unsigned long l;
+ if((*c < '0') || (*c > '9'))
+ /* most importantly this doesn't allow a leading plus or minus */
+ return FALSE;
+ l = strtoul(c, &endp, 0);
+
+ /* overflow or nothing parsed at all */
+ if(((l == ULONG_MAX) && (errno == ERANGE)) || (endp == c))
+ return FALSE;
+
+#if SIZEOF_LONG > 4
+ /* a value larger than 32 bits */
+ if(l > UINT_MAX)
+ return FALSE;
+#endif
+
+ parts[n] = l;
+ c = endp;
+
+ switch (*c) {
+ case '.' :
+ if(n == 3)
+ return FALSE;
+ n++;
+ c++;
+ break;
+
+ case '\0':
+ done = TRUE;
+ break;
+
+ default:
+ return FALSE;
+ }
+ }
+
+ /* this is deemed a valid IPv4 numerical address */
+
+ switch(n) {
+ case 0: /* a -- 32 bits */
+ msnprintf(outp, olen, "%u.%u.%u.%u",
+ parts[0] >> 24, (parts[0] >> 16) & 0xff,
+ (parts[0] >> 8) & 0xff, parts[0] & 0xff);
+ break;
+ case 1: /* a.b -- 8.24 bits */
+ if((parts[0] > 0xff) || (parts[1] > 0xffffff))
+ return FALSE;
+ msnprintf(outp, olen, "%u.%u.%u.%u",
+ parts[0], (parts[1] >> 16) & 0xff,
+ (parts[1] >> 8) & 0xff, parts[1] & 0xff);
+ break;
+ case 2: /* a.b.c -- 8.8.16 bits */
+ if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xffff))
+ return FALSE;
+ msnprintf(outp, olen, "%u.%u.%u.%u",
+ parts[0], parts[1], (parts[2] >> 8) & 0xff,
+ parts[2] & 0xff);
+ break;
+ case 3: /* a.b.c.d -- 8.8.8.8 bits */
+ if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff) ||
+ (parts[3] > 0xff))
+ return FALSE;
+ msnprintf(outp, olen, "%u.%u.%u.%u",
+ parts[0], parts[1], parts[2], parts[3]);
+ break;
+ }
+ return TRUE;
+}
+
static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
{
char *path;
@@ -899,6 +987,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
}
if(hostname) {
+ char normalized_ipv4[sizeof("255.255.255.255") + 1];
/*
* Parse the login details and strip them out of the host name.
*/
@@ -922,7 +1011,10 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
return result;
}
- u->host = strdup(hostname);
+ if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4)))
+ u->host = strdup(normalized_ipv4);
+ else
+ u->host = strdup(hostname);
if(!u->host)
return CURLUE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index f7d60b249..fb905c36c 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -253,6 +253,7 @@ struct ssl_primary_config {
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
struct curl_blob *cert_blob;
+ struct curl_blob *ca_info_blob;
char *curves; /* list of curves to use */
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
@@ -286,6 +287,8 @@ struct ssl_config_data {
BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation
list errors */
BIT(native_ca_store); /* use the native ca store of operating system */
+ BIT(auto_client_cert); /* automatically locate and use a client
+ certificate for authentication (Schannel) */
};
struct ssl_general_config {
@@ -371,6 +374,15 @@ struct kerberos5data {
};
#endif
+/* Struct used for SCRAM-SHA-1 authentication */
+#ifdef USE_GSASL
+#include <gsasl.h>
+struct gsasldata {
+ Gsasl *ctx;
+ Gsasl_session *client;
+};
+#endif
+
/* Struct used for NTLM challenge-response authentication */
#if defined(USE_NTLM)
struct ntlmdata {
@@ -782,12 +794,16 @@ struct Curl_handler {
struct connectdata *conn,
unsigned int checks_to_perform);
+ /* attach() attaches this transfer to this connection */
+ 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 */
unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */
+
};
#define PROTOPT_NONE 0 /* nothing extra */
@@ -846,25 +862,8 @@ struct proxy_info {
char *passwd; /* proxy password string, allocated */
};
-/* struct for HTTP CONNECT state data */
-struct http_connect_state {
- struct dynbuf rcvbuf;
- enum keeponval {
- KEEPON_DONE,
- KEEPON_CONNECT,
- KEEPON_IGNORE
- } keepon;
- curl_off_t cl; /* size of content to read and ignore */
- enum {
- TUNNEL_INIT, /* init/default/no tunnel state */
- TUNNEL_CONNECT, /* CONNECT has been sent off */
- TUNNEL_COMPLETE /* CONNECT response received completely */
- } tunnel_state;
- BIT(chunked_encoding);
- BIT(close_connection);
-};
-
struct ldapconninfo;
+struct http_connect_state;
/* for the (SOCKS) connect state machine */
enum connect_t {
@@ -902,10 +901,6 @@ struct connstate {
* unique for an entire connection.
*/
struct connectdata {
- /* 'data' is the CURRENT Curl_easy using this connection -- take great
- caution that this might very well vary between different times this
- connection is used! */
- struct Curl_easy *data;
struct connstate cnnct;
struct Curl_llist_element bundle_node; /* conncache */
@@ -981,12 +976,8 @@ struct connectdata {
char *user; /* user name string, allocated */
char *passwd; /* password string, allocated */
char *options; /* options string, allocated */
-
char *sasl_authzid; /* authorisation identity string, allocated */
-
- int httpversion; /* the HTTP version*10 reported by the server */
- int rtspversion; /* the RTSP version*10 reported by the server */
-
+ 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 */
@@ -1065,6 +1056,10 @@ struct connectdata {
CtxtHandle *sslContext;
#endif
+#ifdef USE_GSASL
+ struct gsasldata gsasl;
+#endif
+
#if defined(USE_NTLM)
curlntlm http_ntlm_state;
curlntlm proxy_ntlm_state;
@@ -1157,9 +1152,9 @@ struct PureInfo {
reused, in the connection cache. */
char conn_primary_ip[MAX_IPADR_LEN];
- long conn_primary_port;
+ int conn_primary_port;
char conn_local_ip[MAX_IPADR_LEN];
- long conn_local_port;
+ int conn_local_port;
const char *conn_scheme;
unsigned int conn_protocol;
struct curl_certinfo certs; /* info about the certs, only populated in
@@ -1316,8 +1311,6 @@ struct urlpieces {
struct UrlState {
/* Points to the connection cache */
struct conncache *conn_cache;
- int retrycount; /* number of retries on a new connection */
-
/* buffers to store authentication data in, as parsed from input options */
struct curltime keeps_speed; /* for the progress meter really */
@@ -1334,6 +1327,7 @@ struct UrlState {
following not keep sending user+password... This is
strdup() data.
*/
+ int retrycount; /* number of retries on a new connection */
int first_remote_port; /* remote port of the first (not followed) request */
struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
long sessionage; /* number of the most recent session */
@@ -1341,6 +1335,7 @@ struct UrlState {
unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
int os_errno; /* filled in with errno whenever an error occurs */
char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
+ long followlocation; /* redirect counter */
#ifdef HAVE_SIGNAL
/* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
void (*prev_signal)(int sig);
@@ -1365,9 +1360,10 @@ struct UrlState {
/* a place to store the most recently set FTP entrypath */
char *most_recent_ftp_entrypath;
-
- int httpversion; /* the lowest HTTP version*10 reported by any server
- involved in this request */
+ unsigned char httpwant; /* when non-zero, a specific HTTP version requested
+ to be used in the library's request(s) */
+ unsigned char httpversion; /* the lowest HTTP version*10 reported by any
+ server involved in this request */
#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__)
/* do FTP line-end conversions on most platforms */
@@ -1400,9 +1396,13 @@ struct UrlState {
int stream_weight;
CURLU *uh; /* URL handle for the current parsed URL */
struct urlpieces up;
-#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
-#endif
+ char *url; /* work URL, copied from UserDefined */
+ char *referer; /* referer string */
+ struct curl_slist *cookielist; /* list of cookie files set by
+ curl_easy_setopt(COOKIEFILE) calls */
+ struct curl_slist *resolve; /* set to point to the set.resolve list when
+ this should be dealt with in pretransfer */
#ifndef CURL_DISABLE_HTTP
size_t trailers_bytes_sent;
struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
@@ -1427,6 +1427,12 @@ struct UrlState {
char *cookiehost;
char *rtsp_transport;
char *te; /* TE: request header */
+
+ /* transfer credentials */
+ char *user;
+ char *passwd;
+ char *proxyuser;
+ char *proxypasswd;
} aptr;
#ifdef CURLDEBUG
@@ -1454,32 +1460,16 @@ struct UrlState {
BIT(use_range);
BIT(rangestringalloc); /* the range string is malloc()'ed */
BIT(done); /* set to FALSE when Curl_init_do() is called and set to TRUE
- when multi_done() is called, to prevent multi_done() to get
- invoked twice when the multi interface is used. */
+ when multi_done() is called, to prevent multi_done() to get
+ invoked twice when the multi interface is used. */
BIT(stream_depends_e); /* set or don't set the Exclusive bit */
BIT(previouslypending); /* this transfer WAS in the multi->pending queue */
BIT(cookie_engine);
-};
-
-
-/*
- * This 'DynamicStatic' struct defines dynamic states that actually change
- * values in the 'UserDefined' area, which MUST be taken into consideration
- * if the UserDefined struct is cloned or similar. You can probably just
- * copy these, but each one indicate a special action on other data.
- */
-
-struct DynamicStatic {
- char *url; /* work URL, copied from UserDefined */
- char *referer; /* referer string */
- struct curl_slist *cookielist; /* list of cookie files set by
- curl_easy_setopt(COOKIEFILE) calls */
- struct curl_slist *resolve; /* set to point to the set.resolve list when
- this should be dealt with in pretransfer */
+ BIT(prefer_ascii); /* ASCII rather than binary */
+ BIT(list_only); /* list directory contents */
BIT(url_alloc); /* URL string is malloc()'ed */
BIT(referer_alloc); /* referer string is malloc()ed */
- BIT(wildcard_resolve); /* Set to true if any resolve change is a
- wildcard */
+ BIT(wildcard_resolve); /* Set to true if any resolve change is a wildcard */
};
/*
@@ -1502,9 +1492,9 @@ struct Curl_multi; /* declared and used only in multi.c */
* are catered for in curl_easy_setopt_ccsid()
*/
enum dupstring {
- STRING_CERT_ORIG, /* client certificate file name */
+ STRING_CERT, /* client certificate file name */
STRING_CERT_PROXY, /* client certificate file name */
- STRING_CERT_TYPE_ORIG, /* format for certificate (default: PEM)*/
+ STRING_CERT_TYPE, /* format for certificate (default: PEM)*/
STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/
STRING_COOKIE, /* HTTP cookie string to send */
STRING_COOKIEJAR, /* dump all cookies to this file */
@@ -1515,11 +1505,11 @@ enum dupstring {
STRING_FTP_ACCOUNT, /* ftp account data */
STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
STRING_FTPPORT, /* port to send with the FTP PORT command */
- STRING_KEY_ORIG, /* private key file name */
+ STRING_KEY, /* private key file name */
STRING_KEY_PROXY, /* private key file name */
- STRING_KEY_PASSWD_ORIG, /* plain text private key password */
+ STRING_KEY_PASSWD, /* plain text private key password */
STRING_KEY_PASSWD_PROXY, /* plain text private key password */
- STRING_KEY_TYPE_ORIG, /* format for private key (default: PEM) */
+ STRING_KEY_TYPE, /* format for private key (default: PEM) */
STRING_KEY_TYPE_PROXY, /* format for private key (default: PEM) */
STRING_KRB_LEVEL, /* krb security level */
STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find
@@ -1529,22 +1519,22 @@ enum dupstring {
STRING_SET_RANGE, /* range, if used */
STRING_SET_REFERER, /* custom string for the HTTP referer field */
STRING_SET_URL, /* what original URL to work on */
- STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */
+ STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */
STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */
- STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */
+ STRING_SSL_CAFILE, /* certificate file to verify peer against */
STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */
- STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */
+ STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */
STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */
- STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */
+ STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */
- STRING_SSL_CIPHER13_LIST_ORIG, /* list of TLS 1.3 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_ORIG, /* crl file to check certificate */
+ STRING_SSL_CRLFILE, /* crl file to check certificate */
STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
- STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */
+ STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */
STRING_SSL_ENGINE, /* name of ssl engine */
STRING_USERNAME, /* <username>, if used */
@@ -1565,9 +1555,9 @@ enum dupstring {
STRING_SERVICE_NAME, /* Service name */
STRING_MAIL_FROM,
STRING_MAIL_AUTH,
- STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth <username> */
+ STRING_TLSAUTH_USERNAME, /* TLS auth <username> */
STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth <username> */
- STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth <password> */
+ STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth <password> */
STRING_BEARER, /* <bearer>, if used */
STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */
@@ -1596,12 +1586,14 @@ enum dupstring {
};
enum dupblob {
- BLOB_CERT_ORIG,
+ BLOB_CERT,
BLOB_CERT_PROXY,
- BLOB_KEY_ORIG,
+ BLOB_KEY,
BLOB_KEY_PROXY,
- BLOB_SSL_ISSUERCERT_ORIG,
+ BLOB_SSL_ISSUERCERT,
BLOB_SSL_ISSUERCERT_PROXY,
+ BLOB_CAINFO,
+ BLOB_CAINFO_PROXY,
BLOB_LAST
};
@@ -1625,7 +1617,6 @@ struct UserDefined {
unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */
unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */
unsigned long socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */
- long followlocation; /* as in HTTP Location: */
long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1
for infinity */
@@ -1665,7 +1656,7 @@ struct UserDefined {
curl_conv_callback convtonetwork;
/* function to convert from UTF-8 encoding: */
curl_conv_callback convfromutf8;
-#ifdef USE_HSTS
+#ifndef CURL_DISABLE_HSTS
curl_hstsread_callback hsts_read;
void *hsts_read_userp;
curl_hstswrite_callback hsts_write;
@@ -1708,11 +1699,9 @@ struct UserDefined {
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 */
-#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
Curl_HttpReq method; /* what kind of HTTP request (if any) is this */
-#endif
- long httpversion; /* when non-zero, a specific HTTP version requested to
- be used in the library's request(s) */
+ 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 */
#ifndef CURL_DISABLE_PROXY
struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
@@ -1720,8 +1709,8 @@ struct UserDefined {
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 */
- size_t upload_buffer_size; /* size of upload buffer to use,
- keep it >= CURL_MAX_WRITE_SIZE */
+ unsigned int upload_buffer_size; /* size of upload buffer to use,
+ keep it >= CURL_MAX_WRITE_SIZE */
void *private_data; /* application-private data */
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
unsigned char ipver; /* the CURL_IPRESOLVE_* defines in the public header
@@ -1800,8 +1789,8 @@ struct UserDefined {
BIT(get_filetime); /* get the time and get of the remote file */
BIT(tunnel_thru_httpproxy); /* use CONNECT through a HTTP proxy */
BIT(prefer_ascii); /* ASCII rather than binary */
- BIT(ftp_append); /* append, not overwrite, on upload */
- BIT(ftp_list_only); /* switch FTP command for listing directories */
+ BIT(remote_append); /* append, not overwrite, on upload */
+ BIT(list_only); /* list directory */
#ifndef CURL_DISABLE_FTP
BIT(ftp_use_port); /* use the FTP PORT command */
BIT(ftp_use_epsv); /* if EPSV is to be attempted or not */
@@ -1858,6 +1847,9 @@ struct UserDefined {
BIT(disallow_username_in_url); /* disallow username in url */
BIT(doh); /* DNS-over-HTTPS enabled */
BIT(doh_get); /* use GET for DoH requests, instead of POST */
+ BIT(doh_verifypeer); /* DOH certificate peer verification */
+ BIT(doh_verifyhost); /* DOH certificate hostname verification */
+ BIT(doh_verifystatus); /* DOH certificate status verification */
BIT(http09_allowed); /* allow HTTP/0.9 responses */
BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
recipients */
@@ -1905,8 +1897,8 @@ struct Curl_easy {
the state etc are also kept. This array is mostly used to detect when a
socket is to be removed from the hash. See singlesocket(). */
curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
- int actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in
- sockets[] */
+ unsigned char actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in
+ sockets[] */
int numsocks;
struct Names dns;
@@ -1922,12 +1914,11 @@ struct Curl_easy {
#endif
struct SingleRequest req; /* Request-specific data */
struct UserDefined set; /* values set by the libcurl user */
- struct DynamicStatic change; /* possibly modified userdefined data */
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. */
-#ifdef USE_HSTS
+#ifndef CURL_DISABLE_HSTS
struct hsts *hsts;
#endif
#ifndef CURL_DISABLE_ALTSVC
diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c
index 620dba03e..d17e16f10 100644
--- a/Utilities/cmcurl/lib/vauth/cleartext.c
+++ b/Utilities/cmcurl/lib/vauth/cleartext.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -32,7 +32,6 @@
#include "urldata.h"
#include "vauth/vauth.h"
-#include "curl_base64.h"
#include "curl_md5.h"
#include "warnless.h"
#include "strtok.h"
@@ -51,31 +50,24 @@
*
* Parameters:
*
- * data [in] - The session handle.
* authzid [in] - The authorization identity.
* authcid [in] - The authentication identity.
* passwd [in] - The password.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
- const char *authzid,
+CURLcode Curl_auth_create_plain_message(const char *authzid,
const char *authcid,
const char *passwd,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
- CURLcode result;
char *plainauth;
+ size_t plainlen;
size_t zlen;
size_t clen;
size_t plen;
- size_t plainlen;
- *outlen = 0;
- *outptr = NULL;
zlen = (authzid == NULL ? 0 : strlen(authzid));
clen = strlen(authcid);
plen = strlen(passwd);
@@ -86,23 +78,20 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
plainlen = zlen + clen + plen + 2;
- plainauth = malloc(plainlen);
+ plainauth = malloc(plainlen + 1);
if(!plainauth)
return CURLE_OUT_OF_MEMORY;
/* Calculate the reply */
- if(zlen != 0)
+ if(zlen)
memcpy(plainauth, authzid, zlen);
plainauth[zlen] = '\0';
memcpy(plainauth + zlen + 1, authcid, clen);
plainauth[zlen + clen + 1] = '\0';
memcpy(plainauth + zlen + clen + 2, passwd, plen);
-
- /* Base64 encode the reply */
- result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen);
- free(plainauth);
-
- return result;
+ plainauth[plainlen] = '\0';
+ Curl_bufref_set(out, plainauth, plainlen, curl_free);
+ return CURLE_OK;
}
/*
@@ -113,34 +102,15 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
*
* Parameters:
*
- * data [in] - The session handle.
* valuep [in] - The user name or user's password.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_auth_create_login_message(struct Curl_easy *data,
- const char *valuep, char **outptr,
- size_t *outlen)
+CURLcode Curl_auth_create_login_message(const char *valuep, struct bufref *out)
{
- size_t vlen = strlen(valuep);
-
- if(!vlen) {
- /* Calculate an empty reply */
- *outptr = strdup("=");
- if(*outptr) {
- *outlen = (size_t) 1;
- return CURLE_OK;
- }
-
- *outlen = 0;
- return CURLE_OUT_OF_MEMORY;
- }
-
- /* Base64 encode the value */
- return Curl_base64_encode(data, valuep, vlen, outptr, outlen);
+ Curl_bufref_set(out, valuep, strlen(valuep), NULL);
+ return CURLE_OK;
}
/*
@@ -151,20 +121,16 @@ CURLcode Curl_auth_create_login_message(struct Curl_easy *data,
*
* Parameters:
*
- * data [in] - The session handle.
* user [in] - The user name.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_auth_create_external_message(struct Curl_easy *data,
- const char *user, char **outptr,
- size_t *outlen)
+CURLcode Curl_auth_create_external_message(const char *user,
+ struct bufref *out)
{
/* This is the same formatting as the login message */
- return Curl_auth_create_login_message(data, user, outptr, outlen);
+ return Curl_auth_create_login_message(user, out);
}
#endif /* if no users */
diff --git a/Utilities/cmcurl/lib/vauth/cram.c b/Utilities/cmcurl/lib/vauth/cram.c
index 1a376259a..9ddb0ac37 100644
--- a/Utilities/cmcurl/lib/vauth/cram.c
+++ b/Utilities/cmcurl/lib/vauth/cram.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -30,7 +30,6 @@
#include "urldata.h"
#include "vauth/vauth.h"
-#include "curl_base64.h"
#include "curl_hmac.h"
#include "curl_md5.h"
#include "warnless.h"
@@ -40,69 +39,31 @@
#include "curl_memory.h"
#include "memdebug.h"
-/*
- * Curl_auth_decode_cram_md5_message()
- *
- * This is used to decode an already encoded CRAM-MD5 challenge message.
- *
- * Parameters:
- *
- * chlg64 [in] - The base64 encoded challenge message.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
- *
- * Returns CURLE_OK on success.
- */
-CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr,
- size_t *outlen)
-{
- CURLcode result = CURLE_OK;
- size_t chlg64len = strlen(chlg64);
-
- *outptr = NULL;
- *outlen = 0;
-
- /* Decode the challenge if necessary */
- if(chlg64len && *chlg64 != '=')
- result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen);
-
- return result;
-}
/*
* Curl_auth_create_cram_md5_message()
*
- * This is used to generate an already encoded CRAM-MD5 response message ready
- * for sending to the recipient.
+ * This is used to generate a CRAM-MD5 response message ready for sending to
+ * the recipient.
*
* Parameters:
*
- * data [in] - The session handle.
* chlg [in] - The challenge.
* userp [in] - The user name.
* passwdp [in] - The user's password.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data,
- const char *chlg,
+CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg,
const char *userp,
const char *passwdp,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
- CURLcode result = CURLE_OK;
- size_t chlglen = 0;
struct HMAC_context *ctxt;
unsigned char digest[MD5_DIGEST_LEN];
char *response;
- if(chlg)
- chlglen = strlen(chlg);
-
/* Compute the digest using the password as the key */
ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
(const unsigned char *) passwdp,
@@ -111,9 +72,9 @@ CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
/* Update the digest with the given challenge */
- if(chlglen > 0)
- Curl_HMAC_update(ctxt, (const unsigned char *) chlg,
- curlx_uztoui(chlglen));
+ if(Curl_bufref_len(chlg))
+ Curl_HMAC_update(ctxt, Curl_bufref_ptr(chlg),
+ curlx_uztoui(Curl_bufref_len(chlg)));
/* Finalise the digest */
Curl_HMAC_final(ctxt, digest);
@@ -127,12 +88,8 @@ CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data,
if(!response)
return CURLE_OUT_OF_MEMORY;
- /* Base64 encode the response */
- result = Curl_base64_encode(data, response, 0, outptr, outlen);
-
- free(response);
-
- return result;
+ Curl_bufref_set(out, response, strlen(response), curl_free);
+ return CURLE_OK;
}
#endif /* !CURL_DISABLE_CRYPTO_AUTH */
diff --git a/Utilities/cmcurl/lib/vauth/digest.c b/Utilities/cmcurl/lib/vauth/digest.c
index 559852fcb..a04ffab6f 100644
--- a/Utilities/cmcurl/lib/vauth/digest.c
+++ b/Utilities/cmcurl/lib/vauth/digest.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -254,7 +254,7 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value)
*
* Parameters:
*
- * chlg64 [in] - The base64 encoded challenge message.
+ * chlgref [in] - The challenge message.
* nonce [in/out] - The buffer where the nonce will be stored.
* nlen [in] - The length of the nonce buffer.
* realm [in/out] - The buffer where the realm will be stored.
@@ -266,55 +266,35 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value)
*
* Returns CURLE_OK on success.
*/
-static CURLcode auth_decode_digest_md5_message(const char *chlg64,
+static CURLcode auth_decode_digest_md5_message(const struct bufref *chlgref,
char *nonce, size_t nlen,
char *realm, size_t rlen,
char *alg, size_t alen,
char *qop, size_t qlen)
{
- CURLcode result = CURLE_OK;
- unsigned char *chlg = NULL;
- size_t chlglen = 0;
- size_t chlg64len = strlen(chlg64);
-
- /* Decode the base-64 encoded challenge message */
- if(chlg64len && *chlg64 != '=') {
- result = Curl_base64_decode(chlg64, &chlg, &chlglen);
- if(result)
- return result;
- }
+ const char *chlg = (const char *) Curl_bufref_ptr(chlgref);
/* Ensure we have a valid challenge message */
- if(!chlg)
+ if(!Curl_bufref_len(chlgref))
return CURLE_BAD_CONTENT_ENCODING;
/* Retrieve nonce string from the challenge */
- if(!auth_digest_get_key_value((char *) chlg, "nonce=\"", nonce, nlen,
- '\"')) {
- free(chlg);
+ if(!auth_digest_get_key_value(chlg, "nonce=\"", nonce, nlen, '\"'))
return CURLE_BAD_CONTENT_ENCODING;
- }
/* Retrieve realm string from the challenge */
- if(!auth_digest_get_key_value((char *) chlg, "realm=\"", realm, rlen,
- '\"')) {
+ if(!auth_digest_get_key_value(chlg, "realm=\"", realm, rlen, '\"')) {
/* Challenge does not have a realm, set empty string [RFC2831] page 6 */
strcpy(realm, "");
}
/* Retrieve algorithm string from the challenge */
- if(!auth_digest_get_key_value((char *) chlg, "algorithm=", alg, alen, ',')) {
- free(chlg);
+ if(!auth_digest_get_key_value(chlg, "algorithm=", alg, alen, ','))
return CURLE_BAD_CONTENT_ENCODING;
- }
/* Retrieve qop-options string from the challenge */
- if(!auth_digest_get_key_value((char *) chlg, "qop=\"", qop, qlen, '\"')) {
- free(chlg);
+ if(!auth_digest_get_key_value(chlg, "qop=\"", qop, qlen, '\"'))
return CURLE_BAD_CONTENT_ENCODING;
- }
-
- free(chlg);
return CURLE_OK;
}
@@ -342,22 +322,20 @@ bool Curl_auth_is_digest_supported(void)
* Parameters:
*
* data [in] - The session handle.
- * chlg64 [in] - The base64 encoded challenge message.
+ * chlg [in] - The challenge message.
* userp [in] - The user name.
* passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
- const char *chlg64,
+ const struct bufref *chlg,
const char *userp,
const char *passwdp,
const char *service,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
size_t i;
struct MD5_context *ctxt;
@@ -378,9 +356,10 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
char *spn = NULL;
/* Decode the challenge message */
- CURLcode result = auth_decode_digest_md5_message(chlg64, nonce,
- sizeof(nonce), realm,
- sizeof(realm), algorithm,
+ CURLcode result = auth_decode_digest_md5_message(chlg,
+ nonce, sizeof(nonce),
+ realm, sizeof(realm),
+ algorithm,
sizeof(algorithm),
qop_options,
sizeof(qop_options));
@@ -500,11 +479,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(!response)
return CURLE_OUT_OF_MEMORY;
- /* Base64 encode the response */
- result = Curl_base64_encode(data, response, 0, outptr, outlen);
-
- free(response);
-
+ /* Return the response. */
+ Curl_bufref_set(out, response, strlen(response), curl_free);
return result;
}
diff --git a/Utilities/cmcurl/lib/vauth/digest_sspi.c b/Utilities/cmcurl/lib/vauth/digest_sspi.c
index dad947a37..2602ffd36 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 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2021, 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
@@ -32,7 +32,6 @@
#include "vauth/vauth.h"
#include "vauth/digest.h"
#include "urldata.h"
-#include "curl_base64.h"
#include "warnless.h"
#include "curl_multibyte.h"
#include "sendf.h"
@@ -79,28 +78,24 @@ bool Curl_auth_is_digest_supported(void)
* Parameters:
*
* data [in] - The session handle.
- * chlg64 [in] - The base64 encoded challenge message.
+ * chlg [in] - The challenge message.
* userp [in] - The user name in the format User or Domain\User.
* passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
- const char *chlg64,
+ const struct bufref *chlg,
const char *userp,
const char *passwdp,
const char *service,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
CURLcode result = CURLE_OK;
TCHAR *spn = NULL;
- size_t chlglen = 0;
size_t token_max = 0;
- unsigned char *input_token = NULL;
unsigned char *output_token = NULL;
CredHandle credentials;
CtxtHandle context;
@@ -115,17 +110,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
unsigned long attrs;
TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
- /* Decode the base-64 encoded challenge message */
- if(strlen(chlg64) && *chlg64 != '=') {
- result = Curl_base64_decode(chlg64, &input_token, &chlglen);
- if(result)
- return result;
- }
-
/* Ensure we have a valid challenge message */
- if(!input_token) {
+ if(!Curl_bufref_len(chlg)) {
infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n");
-
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -133,8 +120,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
&SecurityPackage);
if(status != SEC_E_OK) {
- free(input_token);
-
failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
@@ -146,18 +131,13 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
/* Allocate our response buffer */
output_token = malloc(token_max);
- if(!output_token) {
- free(input_token);
-
+ if(!output_token)
return CURLE_OUT_OF_MEMORY;
- }
/* Generate our SPN */
spn = Curl_auth_build_spn(service, data->conn->host.name, NULL);
if(!spn) {
free(output_token);
- free(input_token);
-
return CURLE_OUT_OF_MEMORY;
}
@@ -167,8 +147,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(result) {
free(spn);
free(output_token);
- free(input_token);
-
return result;
}
@@ -190,8 +168,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
Curl_sspi_free_identity(p_identity);
free(spn);
free(output_token);
- free(input_token);
-
return CURLE_LOGIN_DENIED;
}
@@ -200,8 +176,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
chlg_desc.cBuffers = 1;
chlg_desc.pBuffers = &chlg_buf;
chlg_buf.BufferType = SECBUFFER_TOKEN;
- chlg_buf.pvBuffer = input_token;
- chlg_buf.cbBuffer = curlx_uztoul(chlglen);
+ chlg_buf.pvBuffer = (void *) Curl_bufref_ptr(chlg);
+ chlg_buf.cbBuffer = curlx_uztoul(Curl_bufref_len(chlg));
/* Setup the response "output" security buffer */
resp_desc.ulVersion = SECBUFFER_VERSION;
@@ -227,7 +203,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
Curl_sspi_free_identity(p_identity);
free(spn);
free(output_token);
- free(input_token);
if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
@@ -238,9 +213,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
return CURLE_AUTH_ERROR;
}
- /* Base64 encode the response */
- result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer,
- outptr, outlen);
+ /* Return the response. */
+ Curl_bufref_set(out, output_token, resp_buf.cbBuffer, curl_free);
/* Free our handles */
s_pSecFn->DeleteSecurityContext(&context);
@@ -252,12 +226,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
/* Free the SPN */
free(spn);
- /* Free the response buffer */
- free(output_token);
-
- /* Free the decoded challenge message */
- free(input_token);
-
return result;
}
diff --git a/Utilities/cmcurl/lib/vauth/gsasl.c b/Utilities/cmcurl/lib/vauth/gsasl.c
new file mode 100644
index 000000000..40fef53c9
--- /dev/null
+++ b/Utilities/cmcurl/lib/vauth/gsasl.c
@@ -0,0 +1,124 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020 - 2021, 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
+ * 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.
+ *
+ * RFC5802 SCRAM-SHA-1 authentication
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_GSASL
+
+#include <curl/curl.h>
+
+#include "vauth/vauth.h"
+#include "urldata.h"
+#include "sendf.h"
+
+#include <gsasl.h>
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+bool Curl_auth_gsasl_is_supported(struct Curl_easy *data,
+ const char *mech,
+ struct gsasldata *gsasl)
+{
+ int res;
+
+ res = gsasl_init(&gsasl->ctx);
+ if(res != GSASL_OK) {
+ failf(data, "gsasl init: %s\n", gsasl_strerror(res));
+ return FALSE;
+ }
+
+ res = gsasl_client_start(gsasl->ctx, mech, &gsasl->client);
+ if(res != GSASL_OK) {
+ gsasl_done(gsasl->ctx);
+ return FALSE;
+ }
+
+ return true;
+}
+
+CURLcode Curl_auth_gsasl_start(struct Curl_easy *data,
+ const char *userp,
+ const char *passwdp,
+ struct gsasldata *gsasl)
+{
+#if GSASL_VERSION_NUMBER >= 0x010b00
+ int res;
+ res =
+#endif
+ gsasl_property_set(gsasl->client, GSASL_AUTHID, userp);
+#if GSASL_VERSION_NUMBER >= 0x010b00
+ if(res != GSASL_OK) {
+ failf(data, "setting AUTHID failed: %s\n", gsasl_strerror(res));
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif
+
+#if GSASL_VERSION_NUMBER >= 0x010b00
+ res =
+#endif
+ gsasl_property_set(gsasl->client, GSASL_PASSWORD, passwdp);
+#if GSASL_VERSION_NUMBER >= 0x010b00
+ if(res != GSASL_OK) {
+ failf(data, "setting PASSWORD failed: %s\n", gsasl_strerror(res));
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif
+
+ (void)data;
+
+ return CURLE_OK;
+}
+
+CURLcode Curl_auth_gsasl_token(struct Curl_easy *data,
+ const struct bufref *chlg,
+ struct gsasldata *gsasl,
+ struct bufref *out)
+{
+ int res;
+ char *response;
+ size_t outlen;
+
+ res = gsasl_step(gsasl->client,
+ (const char *) Curl_bufref_ptr(chlg), Curl_bufref_len(chlg),
+ &response, &outlen);
+ if(res != GSASL_OK && res != GSASL_NEEDS_MORE) {
+ failf(data, "GSASL step: %s\n", gsasl_strerror(res));
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ Curl_bufref_set(out, response, outlen, gsasl_free);
+ return CURLE_OK;
+}
+
+void Curl_auth_gsasl_cleanup(struct gsasldata *gsasl)
+{
+ gsasl_finish(gsasl->client);
+ gsasl->client = NULL;
+
+ gsasl_done(gsasl->ctx);
+ gsasl->ctx = NULL;
+}
+#endif
diff --git a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
index 0412815e9..b43982b9b 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 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2021, 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
@@ -32,7 +32,6 @@
#include "vauth/vauth.h"
#include "curl_sasl.h"
#include "urldata.h"
-#include "curl_base64.h"
#include "curl_gssapi.h"
#include "sendf.h"
#include "curl_printf.h"
@@ -70,12 +69,9 @@ bool Curl_auth_is_gssapi_supported(void)
* host [in[ - The host name.
* mutual_auth [in] - Flag specifying whether or not mutual authentication
* is enabled.
- * chlg64 [in] - Pointer to the optional base64 encoded challenge
- * message.
+ * chlg [in] - Optional challenge message.
* krb5 [in/out] - The Kerberos 5 data struct being used and modified.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
@@ -85,13 +81,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
const char *service,
const char *host,
const bool mutual_auth,
- const char *chlg64,
+ const struct bufref *chlg,
struct kerberos5data *krb5,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
CURLcode result = CURLE_OK;
- size_t chlglen = 0;
- unsigned char *chlg = NULL;
OM_uint32 major_status;
OM_uint32 minor_status;
OM_uint32 unused_status;
@@ -127,24 +121,13 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
free(spn);
}
- if(chlg64 && *chlg64) {
- /* Decode the base-64 encoded challenge message */
- if(*chlg64 != '=') {
- result = Curl_base64_decode(chlg64, &chlg, &chlglen);
- if(result)
- return result;
- }
-
- /* Ensure we have a valid challenge message */
- if(!chlg) {
+ if(chlg) {
+ if(!Curl_bufref_len(chlg)) {
infof(data, "GSSAPI handshake failure (empty challenge message)\n");
-
return CURLE_BAD_CONTENT_ENCODING;
}
-
- /* Setup the challenge "input" security buffer */
- input_token.value = chlg;
- input_token.length = chlglen;
+ input_token.value = (void *) Curl_bufref_ptr(chlg);
+ input_token.length = Curl_bufref_len(chlg);
}
major_status = Curl_gss_init_sec_context(data,
@@ -158,9 +141,6 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
mutual_auth,
NULL);
- /* Free the decoded challenge as it is not required anymore */
- free(input_token.value);
-
if(GSS_ERROR(major_status)) {
if(output_token.value)
gss_release_buffer(&unused_status, &output_token);
@@ -172,17 +152,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
}
if(output_token.value && output_token.length) {
- /* Base64 encode the response */
- result = Curl_base64_encode(data, (char *) output_token.value,
- output_token.length, outptr, outlen);
-
+ result = Curl_bufref_memdup(out, output_token.value, output_token.length);
gss_release_buffer(&unused_status, &output_token);
}
- else if(mutual_auth) {
- *outptr = strdup("");
- if(!*outptr)
- result = CURLE_OUT_OF_MEMORY;
- }
+ else
+ Curl_bufref_set(out, mutual_auth? "": NULL, 0, NULL);
return result;
}
@@ -196,24 +170,19 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
* Parameters:
*
* data [in] - The session handle.
- * chlg64 [in] - Pointer to the optional base64 encoded challenge message.
+ * chlg [in] - Optional challenge message.
* krb5 [in/out] - The Kerberos 5 data struct being used and modified.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
- const char *chlg64,
+ const struct bufref *chlg,
struct kerberos5data *krb5,
- char **outptr,
- size_t *outlen)
+ struct bufref *out)
{
CURLcode result = CURLE_OK;
- size_t chlglen = 0;
size_t messagelen = 0;
- unsigned char *chlg = NULL;
unsigned char *message = NULL;
OM_uint32 major_status;
OM_uint32 minor_status;
@@ -228,17 +197,9 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
gss_name_t username = GSS_C_NO_NAME;
gss_buffer_desc username_token;
- /* Decode the base-64 encoded input message */
- if(strlen(chlg64) && *chlg64 != '=') {
- result = Curl_base64_decode(chlg64, &chlg, &chlglen);
- if(result)
- return result;
- }
-
/* Ensure we have a valid challenge message */
- if(!chlg) {
+ if(!Curl_bufref_len(chlg)) {
infof(data, "GSSAPI handshake failure (empty security message)\n");
-
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -249,9 +210,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
if(GSS_ERROR(major_status)) {
Curl_gss_log_error(data, "gss_inquire_context() failed: ",
major_status, minor_status);
-
- free(chlg);
-
return CURLE_AUTH_ERROR;
}
@@ -261,15 +219,12 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
if(GSS_ERROR(major_status)) {
Curl_gss_log_error(data, "gss_display_name() failed: ",
major_status, minor_status);
-
- free(chlg);
-
return CURLE_AUTH_ERROR;
}
/* Setup the challenge "input" security buffer */
- input_token.value = chlg;
- input_token.length = chlglen;
+ input_token.value = (void *) Curl_bufref_ptr(chlg);
+ input_token.length = Curl_bufref_len(chlg);
/* Decrypt the inbound challenge and obtain the qop */
major_status = gss_unwrap(&minor_status, krb5->context, &input_token,
@@ -277,27 +232,20 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
if(GSS_ERROR(major_status)) {
Curl_gss_log_error(data, "gss_unwrap() failed: ",
major_status, minor_status);
-
gss_release_buffer(&unused_status, &username_token);
- free(chlg);
-
return CURLE_BAD_CONTENT_ENCODING;
}
/* Not 4 octets long so fail as per RFC4752 Section 3.1 */
if(output_token.length != 4) {
infof(data, "GSSAPI handshake failure (invalid security data)\n");
-
gss_release_buffer(&unused_status, &username_token);
- free(chlg);
-
return CURLE_BAD_CONTENT_ENCODING;
}
/* Copy the data out and free the challenge as it is not required anymore */
memcpy(&indata, output_token.value, 4);
gss_release_buffer(&unused_status, &output_token);
- free(chlg);
/* Extract the security layer */
sec_layer = indata & 0x000000FF;
@@ -305,7 +253,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
infof(data, "GSSAPI handshake failure (invalid security layer)\n");
gss_release_buffer(&unused_status, &username_token);
-
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -323,7 +270,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
message = malloc(messagelen);
if(!message) {
gss_release_buffer(&unused_status, &username_token);
-
return CURLE_OUT_OF_MEMORY;
}
@@ -352,16 +298,12 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
if(GSS_ERROR(major_status)) {
Curl_gss_log_error(data, "gss_wrap() failed: ",
major_status, minor_status);
-
free(message);
-
return CURLE_AUTH_ERROR;
}
- /* Base64 encode the response */
- result = Curl_base64_encode(data, (char *) output_token.value,
- output_token.length, outptr, outlen);
-
+ /* Return the response. */
+ result = Curl_bufref_memdup(out, output_token.value, output_token.length);
/* Free the output buffer */
gss_release_buffer(&unused_status, &output_token);
diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
index b2d163534..e11064422 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2020, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2021, 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
@@ -30,7 +30,6 @@
#include "vauth/vauth.h"
#include "urldata.h"
-#include "curl_base64.h"
#include "warnless.h"
#include "curl_multibyte.h"
#include "sendf.h"
@@ -81,11 +80,9 @@ bool Curl_auth_is_gssapi_supported(void)
* host [in] - The host name.
* mutual_auth [in] - Flag specifying whether or not mutual authentication
* is enabled.
- * chlg64 [in] - The optional base64 encoded challenge message.
+ * chlg [in] - Optional challenge message.
* krb5 [in/out] - The Kerberos 5 data struct being used and modified.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
@@ -95,13 +92,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
const char *service,
const char *host,
const bool mutual_auth,
- const char *chlg64,
+ const struct bufref *chlg,
struct kerberos5data *krb5,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
CURLcode result = CURLE_OK;
- size_t chlglen = 0;
- unsigned char *chlg = NULL;
CtxtHandle context;
PSecPkgInfo SecurityPackage;
SecBuffer chlg_buf;
@@ -176,18 +171,9 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
- if(chlg64 && *chlg64) {
- /* Decode the base-64 encoded challenge message */
- if(*chlg64 != '=') {
- result = Curl_base64_decode(chlg64, &chlg, &chlglen);
- if(result)
- return result;
- }
-
- /* Ensure we have a valid challenge message */
- if(!chlg) {
+ if(chlg) {
+ if(!Curl_bufref_len(chlg)) {
infof(data, "GSSAPI handshake failure (empty challenge message)\n");
-
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -196,8 +182,8 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
chlg_desc.cBuffers = 1;
chlg_desc.pBuffers = &chlg_buf;
chlg_buf.BufferType = SECBUFFER_TOKEN;
- chlg_buf.pvBuffer = chlg;
- chlg_buf.cbBuffer = curlx_uztoul(chlglen);
+ chlg_buf.pvBuffer = (void *) Curl_bufref_ptr(chlg);
+ chlg_buf.cbBuffer = curlx_uztoul(Curl_bufref_len(chlg));
}
/* Setup the response "output" security buffer */
@@ -220,16 +206,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
&resp_desc, &attrs,
&expiry);
- /* Free the decoded challenge as it is not required anymore */
- free(chlg);
-
- if(status == SEC_E_INSUFFICIENT_MEMORY) {
+ if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
- }
- if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED)
return CURLE_AUTH_ERROR;
- }
if(memcmp(&context, krb5->context, sizeof(context))) {
s_pSecFn->DeleteSecurityContext(krb5->context);
@@ -238,15 +219,12 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
}
if(resp_buf.cbBuffer) {
- /* Base64 encode the response */
- result = Curl_base64_encode(data, (char *) resp_buf.pvBuffer,
- resp_buf.cbBuffer, outptr, outlen);
- }
- else if(mutual_auth) {
- *outptr = strdup("");
- if(!*outptr)
- result = CURLE_OUT_OF_MEMORY;
+ result = Curl_bufref_memdup(out, resp_buf.pvBuffer, resp_buf.cbBuffer);
}
+ else if(mutual_auth)
+ Curl_bufref_set(out, "", 0, NULL);
+ else
+ Curl_bufref_set(out, NULL, 0, NULL);
return result;
}
@@ -260,26 +238,20 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
* Parameters:
*
* data [in] - The session handle.
- * chlg64 [in] - The optional base64 encoded challenge message.
+ * chlg [in] - The optional challenge message.
* krb5 [in/out] - The Kerberos 5 data struct being used and modified.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
- const char *chlg64,
+ const struct bufref *chlg,
struct kerberos5data *krb5,
- char **outptr,
- size_t *outlen)
+ struct bufref *out)
{
- CURLcode result = CURLE_OK;
size_t offset = 0;
- size_t chlglen = 0;
size_t messagelen = 0;
size_t appdatalen = 0;
- unsigned char *chlg = NULL;
unsigned char *trailer = NULL;
unsigned char *message = NULL;
unsigned char *padding = NULL;
@@ -298,17 +270,9 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
SECURITY_STATUS status;
char *user_name;
- /* Decode the base-64 encoded input message */
- if(strlen(chlg64) && *chlg64 != '=') {
- result = Curl_base64_decode(chlg64, &chlg, &chlglen);
- if(result)
- return result;
- }
-
/* Ensure we have a valid challenge message */
- if(!chlg) {
+ if(!Curl_bufref_len(chlg)) {
infof(data, "GSSAPI handshake failure (empty security message)\n");
-
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -316,35 +280,31 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
status = s_pSecFn->QueryContextAttributes(krb5->context,
SECPKG_ATTR_SIZES,
&sizes);
- if(status != SEC_E_OK) {
- free(chlg);
- if(status == SEC_E_INSUFFICIENT_MEMORY)
- return CURLE_OUT_OF_MEMORY;
+ if(status == SEC_E_INSUFFICIENT_MEMORY)
+ return CURLE_OUT_OF_MEMORY;
+ if(status != SEC_E_OK)
return CURLE_AUTH_ERROR;
- }
/* Get the fully qualified username back from the context */
status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials,
SECPKG_CRED_ATTR_NAMES,
&names);
- if(status != SEC_E_OK) {
- free(chlg);
- if(status == SEC_E_INSUFFICIENT_MEMORY)
- return CURLE_OUT_OF_MEMORY;
+ if(status == SEC_E_INSUFFICIENT_MEMORY)
+ return CURLE_OUT_OF_MEMORY;
+ if(status != SEC_E_OK)
return CURLE_AUTH_ERROR;
- }
/* Setup the "input" security buffer */
input_desc.ulVersion = SECBUFFER_VERSION;
input_desc.cBuffers = 2;
input_desc.pBuffers = input_buf;
input_buf[0].BufferType = SECBUFFER_STREAM;
- input_buf[0].pvBuffer = chlg;
- input_buf[0].cbBuffer = curlx_uztoul(chlglen);
+ input_buf[0].pvBuffer = (void *) Curl_bufref_ptr(chlg);
+ input_buf[0].cbBuffer = curlx_uztoul(Curl_bufref_len(chlg));
input_buf[1].BufferType = SECBUFFER_DATA;
input_buf[1].pvBuffer = NULL;
input_buf[1].cbBuffer = 0;
@@ -353,31 +313,23 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop);
if(status != SEC_E_OK) {
infof(data, "GSSAPI handshake failure (empty security message)\n");
-
- free(chlg);
-
return CURLE_BAD_CONTENT_ENCODING;
}
/* Not 4 octets long so fail as per RFC4752 Section 3.1 */
if(input_buf[1].cbBuffer != 4) {
infof(data, "GSSAPI handshake failure (invalid security data)\n");
-
- free(chlg);
-
return CURLE_BAD_CONTENT_ENCODING;
}
/* Copy the data out and free the challenge as it is not required anymore */
memcpy(&indata, input_buf[1].pvBuffer, 4);
s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
- free(chlg);
/* Extract the security layer */
sec_layer = indata & 0x000000FF;
if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) {
infof(data, "GSSAPI handshake failure (invalid security layer)\n");
-
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -479,17 +431,14 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
offset += wrap_buf[1].cbBuffer;
memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer);
- /* Base64 encode the response */
- result = Curl_base64_encode(data, (char *) appdata, appdatalen, outptr,
- outlen);
-
/* Free all of our local buffers */
- free(appdata);
free(padding);
free(message);
free(trailer);
- return result;
+ /* Return the response. */
+ Curl_bufref_set(out, appdata, appdatalen, curl_free);
+ return CURLE_OK;
}
/*
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index a3117f3fe..47e53572c 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -36,7 +36,6 @@
#include "urldata.h"
#include "non-ascii.h"
#include "sendf.h"
-#include "curl_base64.h"
#include "curl_ntlm_core.h"
#include "curl_gethostname.h"
#include "curl_multibyte.h"
@@ -64,10 +63,6 @@
/* "NTLMSSP" signature is always in ASCII regardless of the platform */
#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
-#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff))
-#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \
- ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff))
-
#if DEBUG_ME
# define DEBUG_OUT(x) x
static void ntlm_print_flags(FILE *handle, unsigned long flags)
@@ -161,31 +156,31 @@ static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
* Parameters:
*
* data [in] - The session handle.
- * buffer [in] - The decoded type-2 message.
- * size [in] - The input buffer size, at least 32 bytes.
+ * type2ref [in] - The type-2 message.
* ntlm [in/out] - The NTLM data struct being used and modified.
*
* Returns CURLE_OK on success.
*/
static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
- unsigned char *buffer,
- size_t size,
+ const struct bufref *type2ref,
struct ntlmdata *ntlm)
{
unsigned short target_info_len = 0;
unsigned int target_info_offset = 0;
+ const unsigned char *type2 = Curl_bufref_ptr(type2ref);
+ size_t type2len = Curl_bufref_len(type2ref);
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
(void) data;
#endif
- if(size >= 48) {
- target_info_len = Curl_read16_le(&buffer[40]);
- target_info_offset = Curl_read32_le(&buffer[44]);
+ if(type2len >= 48) {
+ target_info_len = Curl_read16_le(&type2[40]);
+ target_info_offset = Curl_read32_le(&type2[44]);
if(target_info_len > 0) {
- if((target_info_offset >= size) ||
- ((target_info_offset + target_info_len) > size) ||
- (target_info_offset < 48)) {
+ if((target_info_offset > type2len) ||
+ (target_info_offset + target_info_len) > type2len ||
+ target_info_offset < 48) {
infof(data, "NTLM handshake failure (bad type-2 message). "
"Target Info Offset Len is set incorrect by the peer\n");
return CURLE_BAD_CONTENT_ENCODING;
@@ -196,7 +191,7 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
if(!ntlm->target_info)
return CURLE_OUT_OF_MEMORY;
- memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
+ memcpy(ntlm->target_info, &type2[target_info_offset], target_info_len);
}
}
@@ -238,21 +233,20 @@ bool Curl_auth_is_ntlm_supported(void)
/*
* Curl_auth_decode_ntlm_type2_message()
*
- * This is used to decode an already encoded NTLM type-2 message. The message
- * is first decoded from a base64 string into a raw NTLM message and checked
- * for validity before the appropriate data for creating a type-3 message is
- * written to the given NTLM data structure.
+ * This is used to decode an NTLM type-2 message. The raw NTLM message is
+ * checked * for validity before the appropriate data for creating a type-3
+ * message is * written to the given NTLM data structure.
*
* Parameters:
*
* data [in] - The session handle.
- * type2msg [in] - The base64 encoded type-2 message.
+ * type2ref [in] - The type-2 message.
* ntlm [in/out] - The NTLM data struct being used and modified.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
- const char *type2msg,
+ const struct bufref *type2ref,
struct ntlmdata *ntlm)
{
static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
@@ -274,8 +268,8 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
*/
CURLcode result = CURLE_OK;
- unsigned char *type2 = NULL;
- size_t type2_len = 0;
+ const unsigned char *type2 = Curl_bufref_ptr(type2ref);
+ size_t type2len = Curl_bufref_len(type2ref);
#if defined(NTLM_NEEDS_NSS_INIT)
/* Make sure the crypto backend is initialized */
@@ -286,26 +280,12 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
(void)data;
#endif
- /* Decode the base-64 encoded type-2 message */
- if(strlen(type2msg) && *type2msg != '=') {
- result = Curl_base64_decode(type2msg, &type2, &type2_len);
- if(result)
- return result;
- }
-
- /* Ensure we have a valid type-2 message */
- if(!type2) {
- infof(data, "NTLM handshake failure (empty type-2 message)\n");
- return CURLE_BAD_CONTENT_ENCODING;
- }
-
ntlm->flags = 0;
- if((type2_len < 32) ||
+ if((type2len < 32) ||
(memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
(memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
/* This was not a good enough type-2 message */
- free(type2);
infof(data, "NTLM handshake failure (bad type-2 message)\n");
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -314,9 +294,8 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
memcpy(ntlm->nonce, &type2[24], 8);
if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
- result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
+ result = ntlm_decode_type2_target(data, type2ref, ntlm);
if(result) {
- free(type2);
infof(data, "NTLM handshake failure (bad type-2 message)\n");
return result;
}
@@ -331,8 +310,6 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
fprintf(stderr, "**** Header %s\n ", header);
});
- free(type2);
-
return result;
}
@@ -350,8 +327,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
/*
* Curl_auth_create_ntlm_type1_message()
*
- * This is used to generate an already encoded NTLM type-1 message ready for
- * sending to the recipient using the appropriate compile time crypto API.
+ * This is used to generate an NTLM type-1 message ready for sending to the
+ * recipient using the appropriate compile time crypto API.
*
* Parameters:
*
@@ -361,9 +338,7 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
* service [in] - The service type such as http, smtp, pop or imap.
* host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
@@ -373,7 +348,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *service,
const char *hostname,
struct ntlmdata *ntlm,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
/* NTLM type-1 message structure:
@@ -391,7 +366,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
size_t size;
- unsigned char ntlmbuf[NTLM_BUFSIZE];
+ char *ntlmbuf;
const char *host = ""; /* empty */
const char *domain = ""; /* empty */
size_t hostlen = 0;
@@ -399,6 +374,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
size_t hostoff = 0;
size_t domoff = hostoff + hostlen; /* This is 0: remember that host and
domain are empty */
+ (void)data;
(void)userp;
(void)passwdp;
(void)service,
@@ -407,43 +383,46 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
/* Clean up any former leftovers and initialise to defaults */
Curl_auth_cleanup_ntlm(ntlm);
-#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
+#if defined(USE_NTRESPONSES) && \
+ (defined(USE_NTLM2SESSION) || defined(USE_NTLM_V2))
#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
#else
#define NTLM2FLAG 0
#endif
- msnprintf((char *)ntlmbuf, NTLM_BUFSIZE,
- NTLMSSP_SIGNATURE "%c"
- "\x01%c%c%c" /* 32-bit type = 1 */
- "%c%c%c%c" /* 32-bit NTLM flag field */
- "%c%c" /* domain length */
- "%c%c" /* domain allocated space */
- "%c%c" /* domain name offset */
- "%c%c" /* 2 zeroes */
- "%c%c" /* host length */
- "%c%c" /* host allocated space */
- "%c%c" /* host name offset */
- "%c%c" /* 2 zeroes */
- "%s" /* host name */
- "%s", /* domain string */
- 0, /* trailing zero */
- 0, 0, 0, /* part of type-1 long */
-
- LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
- NTLMFLAG_REQUEST_TARGET |
- NTLMFLAG_NEGOTIATE_NTLM_KEY |
- NTLM2FLAG |
- NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
- SHORTPAIR(domlen),
- SHORTPAIR(domlen),
- SHORTPAIR(domoff),
- 0, 0,
- SHORTPAIR(hostlen),
- SHORTPAIR(hostlen),
- SHORTPAIR(hostoff),
- 0, 0,
- host, /* this is empty */
- domain /* this is empty */);
+ ntlmbuf = aprintf(NTLMSSP_SIGNATURE "%c"
+ "\x01%c%c%c" /* 32-bit type = 1 */
+ "%c%c%c%c" /* 32-bit NTLM flag field */
+ "%c%c" /* domain length */
+ "%c%c" /* domain allocated space */
+ "%c%c" /* domain name offset */
+ "%c%c" /* 2 zeroes */
+ "%c%c" /* host length */
+ "%c%c" /* host allocated space */
+ "%c%c" /* host name offset */
+ "%c%c" /* 2 zeroes */
+ "%s" /* host name */
+ "%s", /* domain string */
+ 0, /* trailing zero */
+ 0, 0, 0, /* part of type-1 long */
+
+ LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domoff),
+ 0, 0,
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostoff),
+ 0, 0,
+ host, /* this is empty */
+ domain /* this is empty */);
+
+ if(!ntlmbuf)
+ return CURLE_OUT_OF_MEMORY;
/* Initial packet length */
size = 32 + hostlen + domlen;
@@ -470,8 +449,8 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
fprintf(stderr, "\n****\n");
});
- /* Return with binary blob encoded into base64 */
- return Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
+ Curl_bufref_set(out, ntlmbuf, size, curl_free);
+ return CURLE_OK;
}
/*
@@ -486,9 +465,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
* userp [in] - The user name in the format User or Domain\User.
* passwdp [in] - The user's password.
* ntlm [in/out] - The NTLM data struct being used and modified.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
@@ -496,7 +473,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
struct ntlmdata *ntlm,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
/* NTLM type-3 message structure:
@@ -563,12 +540,20 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
hostlen = strlen(host);
}
-#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2)
+#if defined(USE_NTRESPONSES) && \
+ (defined(USE_NTLM2SESSION) || defined(USE_NTLM_V2))
+ /* We don't support NTLM2 or extended security if we don't have
+ USE_NTRESPONSES */
if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
+# if defined(USE_NTLM_V2)
unsigned char ntbuffer[0x18];
unsigned char entropy[8];
unsigned char ntlmv2hash[0x18];
+ /* Full NTLM version 2
+ Although this cannot be negotiated, it is used here if available, as
+ servers featuring extended security are likely supporting also
+ NTLMv2. */
result = Curl_rand(data, entropy, 8);
if(result)
return result;
@@ -595,21 +580,14 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
return result;
ptr_ntresp = ntlmv2resp;
- }
- else
-#endif
-
-#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
-
-#define CURL_MD5_DIGEST_LENGTH 16 /* fixed size */
-
- /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
- if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) {
+# else /* defined(USE_NTLM_V2) */
unsigned char ntbuffer[0x18];
unsigned char tmp[0x18];
- unsigned char md5sum[CURL_MD5_DIGEST_LENGTH];
+ unsigned char md5sum[MD5_DIGEST_LEN];
unsigned char entropy[8];
+ /* NTLM version 1 with extended security. */
+
/* Need to create 8 bytes random data */
result = Curl_rand(data, entropy, 8);
if(result)
@@ -639,6 +617,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* NTLM v2 session security is a misnomer because it is not NTLM v2.
It is NTLM v1 using the extended session security that is also
in NTLM v2 */
+# endif /* defined(USE_NTLM_V2) */
}
else
#endif
@@ -649,6 +628,8 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
#endif
unsigned char lmbuffer[0x18];
+ /* NTLM version 1 */
+
#ifdef USE_NTRESPONSES
result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
if(result)
@@ -662,6 +643,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
return result;
Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
+ ntlm->flags &= ~NTLMFLAG_NEGOTIATE_NTLM2_KEY;
/* A safer but less compatible alternative is:
* Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
@@ -845,8 +827,8 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
if(result)
return CURLE_CONV_FAILED;
- /* Return with binary blob encoded into base64 */
- result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
+ /* Return the binary blob. */
+ result = Curl_bufref_memdup(out, ntlmbuf, size);
Curl_auth_cleanup_ntlm(ntlm);
diff --git a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
index 07dc97398..1b1a17630 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -28,7 +28,6 @@
#include "vauth/vauth.h"
#include "urldata.h"
-#include "curl_base64.h"
#include "curl_ntlm_core.h"
#include "warnless.h"
#include "curl_multibyte.h"
@@ -78,9 +77,7 @@ bool Curl_auth_is_ntlm_supported(void)
* service [in] - The service type such as http, smtp, pop or imap.
* host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
@@ -90,7 +87,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *service,
const char *host,
struct ntlmdata *ntlm,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
PSecPkgInfo SecurityPackage;
SecBuffer type_1_buf;
@@ -181,9 +178,9 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED)
return CURLE_AUTH_ERROR;
- /* Base64 encode the response */
- return Curl_base64_encode(data, (char *) ntlm->output_token,
- type_1_buf.cbBuffer, outptr, outlen);
+ /* Return the response. */
+ Curl_bufref_set(out, ntlm->output_token, type_1_buf.cbBuffer, NULL);
+ return CURLE_OK;
}
/*
@@ -194,42 +191,34 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
* Parameters:
*
* data [in] - The session handle.
- * type2msg [in] - The base64 encoded type-2 message.
+ * type2 [in] - The type-2 message.
* ntlm [in/out] - The NTLM data struct being used and modified.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
- const char *type2msg,
+ const struct bufref *type2,
struct ntlmdata *ntlm)
{
- CURLcode result = CURLE_OK;
- unsigned char *type2 = NULL;
- size_t type2_len = 0;
-
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
(void) data;
#endif
- /* Decode the base-64 encoded type-2 message */
- if(strlen(type2msg) && *type2msg != '=') {
- result = Curl_base64_decode(type2msg, &type2, &type2_len);
- if(result)
- return result;
- }
-
/* Ensure we have a valid type-2 message */
- if(!type2) {
+ if(!Curl_bufref_len(type2)) {
infof(data, "NTLM handshake failure (empty type-2 message)\n");
-
return CURLE_BAD_CONTENT_ENCODING;
}
- /* Simply store the challenge for use later */
- ntlm->input_token = type2;
- ntlm->input_token_len = type2_len;
+ /* Store the challenge for later use */
+ ntlm->input_token = malloc(Curl_bufref_len(type2) + 1);
+ if(!ntlm->input_token)
+ return CURLE_OUT_OF_MEMORY;
+ memcpy(ntlm->input_token, Curl_bufref_ptr(type2), Curl_bufref_len(type2));
+ ntlm->input_token[Curl_bufref_len(type2)] = '\0';
+ ntlm->input_token_len = Curl_bufref_len(type2);
- return result;
+ return CURLE_OK;
}
/*
@@ -245,9 +234,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
* userp [in] - The user name in the format User or Domain\User.
* passwdp [in] - The user's password.
* ntlm [in/out] - The NTLM data struct being used and modified.
- * outptr [in/out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen [out] - The length of the output message.
+ * out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
@@ -255,7 +242,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
struct ntlmdata *ntlm,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
CURLcode result = CURLE_OK;
SecBuffer type_2_bufs[2];
@@ -331,12 +318,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
return CURLE_AUTH_ERROR;
}
- /* Base64 encode the response */
- result = Curl_base64_encode(data, (char *) ntlm->output_token,
- type_3_buf.cbBuffer, outptr, outlen);
-
+ /* Return the response. */
+ result = Curl_bufref_memdup(out, ntlm->output_token, type_3_buf.cbBuffer);
Curl_auth_cleanup_ntlm(ntlm);
-
return result;
}
diff --git a/Utilities/cmcurl/lib/vauth/oauth2.c b/Utilities/cmcurl/lib/vauth/oauth2.c
index ca5842a7c..a5f16a0bf 100644
--- a/Utilities/cmcurl/lib/vauth/oauth2.c
+++ b/Utilities/cmcurl/lib/vauth/oauth2.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -31,7 +31,6 @@
#include "urldata.h"
#include "vauth/vauth.h"
-#include "curl_base64.h"
#include "warnless.h"
#include "curl_printf.h"
@@ -42,31 +41,26 @@
/*
* Curl_auth_create_oauth_bearer_message()
*
- * This is used to generate an already encoded OAuth 2.0 message ready for
- * sending to the recipient.
+ * This is used to generate an OAuth 2.0 message ready for sending to the
+ * recipient.
*
* Parameters:
*
- * data[in] - The session handle.
* user[in] - The user name.
* host[in] - The host name.
* port[in] - The port(when not Port 80).
* bearer[in] - The bearer token.
- * outptr[in / out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen[out] - The length of the output message.
+ * out[out] - The result storage.
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
- const char *user,
+CURLcode Curl_auth_create_oauth_bearer_message(const char *user,
const char *host,
const long port,
const char *bearer,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
- CURLcode result = CURLE_OK;
- char *oauth = NULL;
+ char *oauth;
/* Generate the message */
if(port == 0 || port == 80)
@@ -78,49 +72,34 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
if(!oauth)
return CURLE_OUT_OF_MEMORY;
- /* Base64 encode the reply */
- result = Curl_base64_encode(data, oauth, strlen(oauth), outptr, outlen);
-
- free(oauth);
-
- return result;
+ Curl_bufref_set(out, oauth, strlen(oauth), curl_free);
+ return CURLE_OK;
}
/*
* Curl_auth_create_xoauth_bearer_message()
*
- * This is used to generate an already encoded XOAuth 2.0 message ready for
- * sending to the recipient.
+ * This is used to generate a XOAuth 2.0 message ready for * sending to the
+ * recipient.
*
* Parameters:
*
- * data[in] - The session handle.
* user[in] - The user name.
* bearer[in] - The bearer token.
- * outptr[in / out] - The address where a pointer to newly allocated memory
- * holding the result will be stored upon completion.
- * outlen[out] - The length of the output message.
+ * out[out] - The result storage.
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data,
- const char *user,
+CURLcode Curl_auth_create_xoauth_bearer_message(const char *user,
const char *bearer,
- char **outptr, size_t *outlen)
+ struct bufref *out)
{
- CURLcode result = CURLE_OK;
-
/* Generate the message */
char *xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
if(!xoauth)
return CURLE_OUT_OF_MEMORY;
- /* Base64 encode the reply */
- result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen);
-
- free(xoauth);
-
- return result;
+ Curl_bufref_set(out, xoauth, strlen(xoauth), curl_free);
+ return CURLE_OK;
}
#endif /* disabled, no users */
-
diff --git a/Utilities/cmcurl/lib/vauth/vauth.c b/Utilities/cmcurl/lib/vauth/vauth.c
index 129b8f8b5..3624fb0c4 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.c
+++ b/Utilities/cmcurl/lib/vauth/vauth.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2020, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2021, 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
@@ -72,6 +72,7 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
{
char *utf8_spn = NULL;
TCHAR *tchar_spn = NULL;
+ TCHAR *dupe_tchar_spn = NULL;
(void) realm;
@@ -84,23 +85,19 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
/* Generate our UTF8 based SPN */
utf8_spn = aprintf("%s/%s", service, host);
- if(!utf8_spn) {
+ if(!utf8_spn)
return NULL;
- }
- /* Allocate our TCHAR based SPN */
+ /* Allocate and return a TCHAR based SPN. Since curlx_convert_UTF8_to_tchar
+ must be freed by curlx_unicodefree we'll dupe the result so that the
+ pointer this function returns can be normally free'd. */
tchar_spn = curlx_convert_UTF8_to_tchar(utf8_spn);
- if(!tchar_spn) {
- free(utf8_spn);
-
+ free(utf8_spn);
+ if(!tchar_spn)
return NULL;
- }
-
- /* Release the UTF8 variant when operating with Unicode */
- curlx_unicodefree(utf8_spn);
-
- /* Return our newly allocated SPN */
- return tchar_spn;
+ dupe_tchar_spn = _tcsdup(tchar_spn);
+ curlx_unicodefree(tchar_spn);
+ return dupe_tchar_spn;
}
#endif /* USE_WINDOWS_SSPI */
diff --git a/Utilities/cmcurl/lib/vauth/vauth.h b/Utilities/cmcurl/lib/vauth/vauth.h
index f25cfc329..ec5b0007f 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.h
+++ b/Utilities/cmcurl/lib/vauth/vauth.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2020, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2021, 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
@@ -24,6 +24,8 @@
#include <curl/curl.h>
+#include "bufref.h"
+
struct Curl_easy;
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
@@ -42,6 +44,10 @@ struct kerberos5data;
struct negotiatedata;
#endif
+#if defined(USE_GSASL)
+struct gsasldata;
+#endif
+
#if defined(USE_WINDOWS_SSPI)
#define GSS_ERROR(status) ((status) & 0x80000000)
#endif
@@ -58,45 +64,37 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
/* This is used to test if the user contains a Windows domain name */
bool Curl_auth_user_contains_domain(const char *user);
-/* This is used to generate a base64 encoded PLAIN cleartext message */
-CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
- const char *authzid,
+/* This is used to generate a PLAIN cleartext message */
+CURLcode Curl_auth_create_plain_message(const char *authzid,
const char *authcid,
const char *passwd,
- char **outptr, size_t *outlen);
+ struct bufref *out);
-/* This is used to generate a base64 encoded LOGIN cleartext message */
-CURLcode Curl_auth_create_login_message(struct Curl_easy *data,
- const char *valuep, char **outptr,
- size_t *outlen);
+/* This is used to generate a LOGIN cleartext message */
+CURLcode Curl_auth_create_login_message(const char *value,
+ struct bufref *out);
-/* This is used to generate a base64 encoded EXTERNAL cleartext message */
-CURLcode Curl_auth_create_external_message(struct Curl_easy *data,
- const char *user, char **outptr,
- size_t *outlen);
+/* This is used to generate an EXTERNAL cleartext message */
+CURLcode Curl_auth_create_external_message(const char *user,
+ struct bufref *out);
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
-/* This is used to decode a CRAM-MD5 challenge message */
-CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr,
- size_t *outlen);
-
/* This is used to generate a CRAM-MD5 response message */
-CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data,
- const char *chlg,
+CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg,
const char *userp,
const char *passwdp,
- char **outptr, size_t *outlen);
+ struct bufref *out);
/* This is used to evaluate if DIGEST is supported */
bool Curl_auth_is_digest_supported(void);
/* This is used to generate a base64 encoded DIGEST-MD5 response message */
CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
- const char *chlg64,
+ const struct bufref *chlg,
const char *userp,
const char *passwdp,
const char *service,
- char **outptr, size_t *outlen);
+ struct bufref *out);
/* This is used to decode a HTTP DIGEST challenge message */
CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
@@ -115,6 +113,27 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
void Curl_auth_digest_cleanup(struct digestdata *digest);
#endif /* !CURL_DISABLE_CRYPTO_AUTH */
+#ifdef USE_GSASL
+/* This is used to evaluate if MECH is supported by gsasl */
+bool Curl_auth_gsasl_is_supported(struct Curl_easy *data,
+ const char *mech,
+ struct gsasldata *gsasl);
+/* This is used to start a gsasl method */
+CURLcode Curl_auth_gsasl_start(struct Curl_easy *data,
+ const char *userp,
+ const char *passwdp,
+ struct gsasldata *gsasl);
+
+/* This is used to process and generate a new SASL token */
+CURLcode Curl_auth_gsasl_token(struct Curl_easy *data,
+ const struct bufref *chlg,
+ struct gsasldata *gsasl,
+ struct bufref *out);
+
+/* This is used to clean up the gsasl specific data */
+void Curl_auth_gsasl_cleanup(struct gsasldata *digest);
+#endif
+
#if defined(USE_NTLM)
/* This is used to evaluate if NTLM is supported */
bool Curl_auth_is_ntlm_supported(void);
@@ -126,12 +145,11 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *service,
const char *host,
struct ntlmdata *ntlm,
- char **outptr,
- size_t *outlen);
+ struct bufref *out);
/* This is used to decode a base64 encoded NTLM type-2 message */
CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
- const char *type2msg,
+ const struct bufref *type2,
struct ntlmdata *ntlm);
/* This is used to generate a base64 encoded NTLM type-3 message */
@@ -139,25 +157,23 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
struct ntlmdata *ntlm,
- char **outptr, size_t *outlen);
+ struct bufref *out);
/* This is used to clean up the NTLM specific data */
void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm);
#endif /* USE_NTLM */
/* This is used to generate a base64 encoded OAuth 2.0 message */
-CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
- const char *user,
+CURLcode Curl_auth_create_oauth_bearer_message(const char *user,
const char *host,
const long port,
const char *bearer,
- char **outptr, size_t *outlen);
+ struct bufref *out);
/* This is used to generate a base64 encoded XOAuth 2.0 message */
-CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data,
- const char *user,
+CURLcode Curl_auth_create_xoauth_bearer_message(const char *user,
const char *bearer,
- char **outptr, size_t *outlen);
+ struct bufref *out);
#if defined(USE_KERBEROS5)
/* This is used to evaluate if GSSAPI (Kerberos V5) is supported */
@@ -171,17 +187,16 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
const char *service,
const char *host,
const bool mutual,
- const char *chlg64,
+ const struct bufref *chlg,
struct kerberos5data *krb5,
- char **outptr, size_t *outlen);
+ struct bufref *out);
/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security
token message */
CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
- const char *input,
+ const struct bufref *chlg,
struct kerberos5data *krb5,
- char **outptr,
- size_t *outlen);
+ struct bufref *out);
/* This is used to clean up the GSSAPI specific data */
void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5);
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index a9102ec1e..b67b9a466 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, 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
@@ -66,6 +66,14 @@
#include <zstd.h>
#endif
+#ifdef USE_GSASL
+#include <gsasl.h>
+#endif
+
+#ifdef USE_OPENLDAP
+#include <ldap.h>
+#endif
+
#ifdef HAVE_BROTLI
static size_t brotli_version(char *buf, size_t bufsz)
{
@@ -100,7 +108,7 @@ static size_t zstd_version(char *buf, size_t bufsz)
* zeros in the data.
*/
-#define VERSION_PARTS 15 /* number of substrings we can concatenate */
+#define VERSION_PARTS 17 /* number of substrings we can concatenate */
char *curl_version(void)
{
@@ -147,6 +155,12 @@ char *curl_version(void)
#ifdef USE_HYPER
char hyper_buf[30];
#endif
+#ifdef USE_GSASL
+ char gsasl_buf[30];
+#endif
+#ifdef USE_OPENLDAP
+ char ldap_buf[30];
+#endif
int i = 0;
int j;
@@ -235,6 +249,29 @@ char *curl_version(void)
msnprintf(hyper_buf, sizeof(hyper_buf), "Hyper/%s", hyper_version());
src[i++] = hyper_buf;
#endif
+#ifdef USE_GSASL
+ msnprintf(gsasl_buf, sizeof(gsasl_buf), "libgsasl/%s",
+ gsasl_check_version(NULL));
+ src[i++] = gsasl_buf;
+#endif
+#ifdef USE_OPENLDAP
+ {
+ LDAPAPIInfo api;
+ api.ldapai_info_version = LDAP_API_INFO_VERSION;
+
+ if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) == LDAP_OPT_SUCCESS) {
+ unsigned int patch = api.ldapai_vendor_version % 100;
+ unsigned int major = api.ldapai_vendor_version / 10000;
+ unsigned int minor =
+ ((api.ldapai_vendor_version - major * 10000) - patch) / 100;
+ msnprintf(ldap_buf, sizeof(ldap_buf), "%s/%u.%u.%u",
+ api.ldapai_vendor_name, major, minor, patch);
+ src[i++] = ldap_buf;
+ ldap_memfree(api.ldapai_vendor_name);
+ ber_memvfree((void **)api.ldapai_extensions);
+ }
+ }
+#endif
DEBUGASSERT(i <= VERSION_PARTS);
@@ -326,7 +363,7 @@ static const char * const protocols[] = {
"sftp",
#endif
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
- (CURL_SIZEOF_CURL_OFF_T > 4)
+ (SIZEOF_CURL_OFF_T > 4)
"smb",
# ifdef USE_SSL
"smbs",
@@ -391,7 +428,7 @@ static curl_version_info_data version_info = {
#ifdef CURLRES_ASYNCH
| CURL_VERSION_ASYNCHDNS
#endif
-#if (CURL_SIZEOF_CURL_OFF_T > 4) && \
+#if (SIZEOF_CURL_OFF_T > 4) && \
( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
| CURL_VERSION_LARGEFILE
#endif
@@ -428,9 +465,12 @@ static curl_version_info_data version_info = {
#ifndef CURL_DISABLE_ALTSVC
| CURL_VERSION_ALTSVC
#endif
-#if defined(USE_HSTS)
+#ifndef CURL_DISABLE_HSTS
| CURL_VERSION_HSTS
#endif
+#if defined(USE_GSASL)
+ | CURL_VERSION_GSASL
+#endif
,
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */
@@ -458,7 +498,8 @@ static curl_version_info_data version_info = {
#endif
0, /* zstd_ver_num */
NULL, /* zstd version */
- NULL /* Hyper version */
+ NULL, /* Hyper version */
+ NULL /* gsasl version */
};
curl_version_info_data *curl_version_info(CURLversion stamp)
@@ -562,6 +603,12 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
}
#endif
+#ifdef USE_GSASL
+ {
+ version_info.gsasl_version = gsasl_check_version(NULL);
+ }
+#endif
+
(void)stamp; /* avoid compiler warnings, we don't use this */
return &version_info;
}
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.c b/Utilities/cmcurl/lib/vquic/ngtcp2.c
index d4d0e8bf4..7f076759b 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.c
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.c
@@ -57,6 +57,8 @@
#define H3BUGF(x) do { } while(0)
#endif
+#define H3_ALPN_H3_29 "\x5h3-29"
+
/*
* This holds outgoing HTTP/3 stream data that is used by nghttp3 until acked.
* It is used as a circular buffer. Add new bytes at the end until it reaches
@@ -224,7 +226,7 @@ static int write_client_handshake(struct quicsocket *qs,
int rv;
crypto_data = &qs->crypto_data[level];
- if(crypto_data->buf == NULL) {
+ if(!crypto_data->buf) {
crypto_data->buf = malloc(4096);
if(!crypto_data->buf)
return 0;
@@ -351,8 +353,8 @@ static int quic_init_ssl(struct quicsocket *qs)
SSL_set_app_data(qs->ssl, qs);
SSL_set_connect_state(qs->ssl);
- alpn = (const uint8_t *)NGHTTP3_ALPN_H3;
- alpnlen = sizeof(NGHTTP3_ALPN_H3) - 1;
+ alpn = (const uint8_t *)H3_ALPN_H3_29;
+ alpnlen = sizeof(H3_ALPN_H3_29) - 1;
if(alpn)
SSL_set_alpn_protos(qs->ssl, alpn, (int)alpnlen);
@@ -529,8 +531,8 @@ static int quic_init_ssl(struct quicsocket *qs)
}
/* strip the first byte (the length) from NGHTTP3_ALPN_H3 */
- alpn.data = (unsigned char *)NGHTTP3_ALPN_H3 + 1;
- alpn.size = sizeof(NGHTTP3_ALPN_H3) - 2;
+ alpn.data = (unsigned char *)H3_ALPN_H3_29 + 1;
+ alpn.size = sizeof(H3_ALPN_H3_29) - 2;
if(alpn.data)
gnutls_alpn_set_protocols(qs->ssl, &alpn, 1, 0);
@@ -580,7 +582,7 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
{
struct quicsocket *qs = (struct quicsocket *)user_data;
ssize_t nconsumed;
- int fin = flags & NGTCP2_STREAM_DATA_FLAG_FIN ? 1 : 0;
+ int fin = (flags & NGTCP2_STREAM_DATA_FLAG_FIN) ? 1 : 0;
(void)offset;
(void)stream_user_data;
@@ -601,7 +603,7 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
static int
cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
- uint64_t offset, size_t datalen, void *user_data,
+ uint64_t offset, uint64_t datalen, void *user_data,
void *stream_user_data)
{
struct quicsocket *qs = (struct quicsocket *)user_data;
@@ -613,7 +615,7 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
(void)stream_user_data;
rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen);
- if(rv != 0) {
+ if(rv) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -632,7 +634,7 @@ static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_close_stream(qs->h3conn, stream_id,
app_error_code);
- if(rv != 0) {
+ if(rv) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -651,7 +653,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
(void)stream_user_data;
rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id);
- if(rv != 0) {
+ if(rv) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -680,7 +682,7 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
(void)stream_user_data;
rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id);
- if(rv != 0) {
+ if(rv) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -739,7 +741,10 @@ static ngtcp2_callbacks ng_callbacks = {
NULL, /* handshake_confirmed */
NULL, /* recv_new_token */
ngtcp2_crypto_delete_crypto_aead_ctx_cb,
- ngtcp2_crypto_delete_crypto_cipher_ctx_cb
+ ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
+ NULL, /* recv_datagram */
+ NULL, /* ack_datagram */
+ NULL /* lost_datagram */
};
/*
@@ -758,7 +763,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
ngtcp2_path path; /* TODO: this must be initialized properly */
struct quicsocket *qs = &conn->hequic[sockindex];
char ipbuf[40];
- long port;
+ int port;
int qfd;
if(qs->conn)
@@ -773,7 +778,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- infof(data, "Connect socket %d over QUIC to %s:%ld\n",
+ infof(data, "Connect socket %d over QUIC to %s:%d\n",
sockfd, ipbuf, port);
qs->version = NGTCP2_PROTO_VER_MAX;
@@ -807,8 +812,8 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
return CURLE_QUIC_CONNECT_ERROR;
ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
- qs->local_addrlen, NULL);
- ngtcp2_addr_init(&path.remote, addr, addrlen, NULL);
+ qs->local_addrlen);
+ ngtcp2_addr_init(&path.remote, addr, addrlen);
rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path,
NGTCP2_PROTO_VER_MIN, &ng_callbacks,
@@ -827,7 +832,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
*/
int Curl_quic_ver(char *p, size_t len)
{
- ngtcp2_info *ng2 = ngtcp2_version(0);
+ const ngtcp2_info *ng2 = ngtcp2_version(0);
nghttp3_info *ht3 = nghttp3_version(0);
return msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
ng2->version_str, ht3->version_str);
@@ -870,8 +875,10 @@ static void qs_disconnect(struct quicsocket *qs)
#endif
qs->ssl = NULL;
#ifdef USE_GNUTLS
- if(qs->cred)
+ if(qs->cred) {
gnutls_certificate_free_credentials(qs->cred);
+ qs->cred = NULL;
+ }
#endif
for(i = 0; i < 3; i++)
Curl_safefree(qs->crypto_data[i].buf);
@@ -927,6 +934,7 @@ static const struct Curl_handler Curl_handler_http3 = {
ng_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ng_conncheck, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
CURLPROTO_HTTP, /* family */
@@ -1291,7 +1299,6 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
{
struct Curl_easy *data = stream_user_data;
struct HTTP *stream = data->req.p.http;
- int rv;
(void)user_data;
if(!data->set.postfields) {
@@ -1302,8 +1309,8 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
if(stream->h3out->used == 0) {
- rv = nghttp3_conn_resume_stream(conn, stream_id);
- if(rv != 0) {
+ int rv = nghttp3_conn_resume_stream(conn, stream_id);
+ if(rv) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
}
@@ -1539,7 +1546,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
}
/* :authority must come before non-pseudo header fields */
- if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
+ if(authority_idx && authority_idx != AUTHORITY_DST_IDX) {
nghttp3_nv authority = nva[authority_idx];
for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
nva[i] = nva[i - 1];
@@ -1730,12 +1737,12 @@ static CURLcode ng_process_ingress(struct Curl_easy *data,
}
ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
- qs->local_addrlen, NULL);
+ qs->local_addrlen);
ngtcp2_addr_init(&path.remote, (struct sockaddr *)&remote_addr,
- remote_addrlen, NULL);
+ remote_addrlen);
rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts);
- if(rv != 0) {
+ if(rv) {
/* TODO Send CONNECTION_CLOSE if possible */
return CURLE_RECV_ERROR;
}
@@ -1779,7 +1786,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
}
rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
- if(rv != 0) {
+ if(rv) {
failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
ngtcp2_strerror(rv));
return CURLE_SEND_ERROR;
@@ -1788,7 +1795,6 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
ngtcp2_path_storage_zero(&ps);
for(;;) {
- outlen = -1;
veccnt = 0;
stream_id = -1;
fin = 0;
@@ -1816,7 +1822,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
assert(ndatalen == -1);
rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
- if(rv != 0) {
+ if(rv) {
failf(data, "nghttp3_conn_block_stream returned error: %s\n",
nghttp3_strerror(rv));
return CURLE_SEND_ERROR;
@@ -1826,7 +1832,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
else if(outlen == NGTCP2_ERR_WRITE_MORE) {
assert(ndatalen >= 0);
rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
- if(rv != 0) {
+ if(rv) {
failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
nghttp3_strerror(rv));
return CURLE_SEND_ERROR;
@@ -1842,7 +1848,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
}
else if(ndatalen >= 0) {
rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
- if(rv != 0) {
+ if(rv) {
failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
nghttp3_strerror(rv));
return CURLE_SEND_ERROR;
diff --git a/Utilities/cmcurl/lib/vquic/quiche.c b/Utilities/cmcurl/lib/vquic/quiche.c
index d138dd3a2..b62d88437 100644
--- a/Utilities/cmcurl/lib/vquic/quiche.c
+++ b/Utilities/cmcurl/lib/vquic/quiche.c
@@ -157,6 +157,7 @@ static const struct Curl_handler Curl_handler_http3 = {
quiche_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
quiche_conncheck, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
CURLPROTO_HTTP, /* family */
@@ -180,7 +181,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
struct quicsocket *qs = &conn->hequic[sockindex];
char *keylog_file = NULL;
char ipbuf[40];
- long port;
+ int port;
#ifdef DEBUG_QUICHE
/* initialize debug log callback only once */
@@ -225,7 +226,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
quiche_config_log_keys(qs->cfg);
qs->conn = quiche_connect(conn->host.name, (const uint8_t *) qs->scid,
- sizeof(qs->scid), qs->cfg);
+ sizeof(qs->scid), addr, addrlen, qs->cfg);
if(!qs->conn) {
failf(data, "can't create quiche connection");
return CURLE_OUT_OF_MEMORY;
@@ -359,22 +360,34 @@ static CURLcode process_ingress(struct Curl_easy *data, int sockfd,
ssize_t recvd;
uint8_t *buf = (uint8_t *)data->state.buffer;
size_t bufsize = data->set.buffer_size;
+ struct sockaddr_storage from;
+ socklen_t from_len;
+ quiche_recv_info recv_info;
+
+ DEBUGASSERT(qs->conn);
/* in case the timeout expired */
quiche_conn_on_timeout(qs->conn);
do {
- recvd = recv(sockfd, buf, bufsize, 0);
+ from_len = sizeof(from);
+
+ recvd = recvfrom(sockfd, buf, bufsize, 0,
+ (struct sockaddr *)&from, &from_len);
+
if((recvd < 0) && ((SOCKERRNO == EAGAIN) || (SOCKERRNO == EWOULDBLOCK)))
break;
if(recvd < 0) {
- failf(data, "quiche: recv() unexpectedly returned %zd "
+ failf(data, "quiche: recvfrom() unexpectedly returned %zd "
"(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd);
return CURLE_RECV_ERROR;
}
- recvd = quiche_conn_recv(qs->conn, buf, recvd);
+ recv_info.from = (struct sockaddr *) &from;
+ recv_info.from_len = from_len;
+
+ recvd = quiche_conn_recv(qs->conn, buf, recvd, &recv_info);
if(recvd == QUICHE_ERR_DONE)
break;
@@ -397,9 +410,10 @@ static CURLcode flush_egress(struct Curl_easy *data, int sockfd,
ssize_t sent;
uint8_t out[1200];
int64_t timeout_ns;
+ quiche_send_info send_info;
do {
- sent = quiche_conn_send(qs->conn, out, sizeof(out));
+ sent = quiche_conn_send(qs->conn, out, sizeof(out), &send_info);
if(sent == QUICHE_ERR_DONE)
break;
@@ -408,9 +422,10 @@ static CURLcode flush_egress(struct Curl_easy *data, int sockfd,
return CURLE_SEND_ERROR;
}
- sent = send(sockfd, out, sent, 0);
+ sent = sendto(sockfd, out, sent, 0,
+ (struct sockaddr *)&send_info.to, send_info.to_len);
if(sent < 0) {
- failf(data, "send() returned %zd", sent);
+ failf(data, "sendto() returned %zd", sent);
return CURLE_SEND_ERROR;
}
} while(1);
@@ -748,7 +763,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
}
/* :authority must come before non-pseudo header fields */
- if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
+ if(authority_idx && authority_idx != AUTHORITY_DST_IDX) {
quiche_h3_header authority = nva[authority_idx];
for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
nva[i] = nva[i - 1];
diff --git a/Utilities/cmcurl/lib/vssh/libssh.c b/Utilities/cmcurl/lib/vssh/libssh.c
index 08896ab5b..d146d15fd 100644
--- a/Utilities/cmcurl/lib/vssh/libssh.c
+++ b/Utilities/cmcurl/lib/vssh/libssh.c
@@ -159,6 +159,7 @@ const struct Curl_handler Curl_handler_scp = {
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
CURLPROTO_SCP, /* family */
@@ -185,6 +186,7 @@ const struct Curl_handler Curl_handler_sftp = {
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
CURLPROTO_SFTP, /* family */
@@ -549,49 +551,48 @@ cleanup:
return rc;
}
-#define MOVE_TO_ERROR_STATE(_r) { \
- state(data, SSH_SESSION_DISCONNECT); \
- sshc->actualcode = _r; \
- rc = SSH_ERROR; \
- break; \
-}
+#define MOVE_TO_ERROR_STATE(_r) do { \
+ state(data, SSH_SESSION_DISCONNECT); \
+ sshc->actualcode = _r; \
+ rc = SSH_ERROR; \
+ } while(0)
-#define MOVE_TO_SFTP_CLOSE_STATE() { \
- state(data, SSH_SFTP_CLOSE); \
- sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
- rc = SSH_ERROR; \
- break; \
-}
+#define MOVE_TO_SFTP_CLOSE_STATE() do { \
+ state(data, SSH_SFTP_CLOSE); \
+ sshc->actualcode = \
+ sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
+ rc = SSH_ERROR; \
+ } while(0)
-#define MOVE_TO_LAST_AUTH \
- if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
- rc = SSH_OK; \
- state(data, SSH_AUTH_PASS_INIT); \
- break; \
- } \
- else { \
- MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
- }
+#define MOVE_TO_LAST_AUTH do { \
+ if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
+ rc = SSH_OK; \
+ state(data, SSH_AUTH_PASS_INIT); \
+ } \
+ else { \
+ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
+ } \
+ } while(0)
-#define MOVE_TO_TERTIARY_AUTH \
- if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
- rc = SSH_OK; \
- state(data, SSH_AUTH_KEY_INIT); \
- break; \
- } \
- else { \
- MOVE_TO_LAST_AUTH; \
- }
+#define MOVE_TO_TERTIARY_AUTH do { \
+ if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
+ rc = SSH_OK; \
+ state(data, SSH_AUTH_KEY_INIT); \
+ } \
+ else { \
+ MOVE_TO_LAST_AUTH; \
+ } \
+ } while(0)
-#define MOVE_TO_SECONDARY_AUTH \
- if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
- rc = SSH_OK; \
- state(data, SSH_AUTH_GSSAPI); \
- break; \
- } \
- else { \
- MOVE_TO_TERTIARY_AUTH; \
- }
+#define MOVE_TO_SECONDARY_AUTH do { \
+ if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
+ rc = SSH_OK; \
+ state(data, SSH_AUTH_GSSAPI); \
+ } \
+ else { \
+ MOVE_TO_TERTIARY_AUTH; \
+ } \
+ } while(0)
static
int myssh_auth_interactive(struct connectdata *conn)
@@ -629,7 +630,7 @@ restart:
rc = SSH_OK;
else if(rc == SSH_AUTH_INFO) {
nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
- if(nprompts != 0)
+ if(nprompts)
return SSH_ERROR;
sshc->kbd_state = 2;
@@ -704,6 +705,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc != SSH_OK) {
failf(data, "Failure establishing ssh session");
MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
+ break;
}
state(data, SSH_HOSTKEY);
@@ -714,6 +716,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
rc = myssh_is_known(data);
if(rc != SSH_OK) {
MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
+ break;
}
state(data, SSH_AUTHLIST);
@@ -735,6 +738,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
else if(rc == SSH_AUTH_ERROR) {
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+ break;
}
sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
@@ -753,6 +757,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
else { /* unsupported authentication method */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+ break;
}
break;
@@ -760,6 +765,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_AUTH_PKEY_INIT:
if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
MOVE_TO_SECONDARY_AUTH;
+ break;
}
/* Two choices, (1) private key was given on CMD,
@@ -775,6 +781,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc != SSH_OK) {
MOVE_TO_SECONDARY_AUTH;
+ break;
}
}
@@ -833,6 +840,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_AUTH_GSSAPI:
if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) {
MOVE_TO_TERTIARY_AUTH;
+ break;
}
rc = ssh_userauth_gssapi(sshc->ssh_session);
@@ -879,6 +887,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
/* Host key authentication is intentionally not implemented */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+ break;
}
state(data, SSH_AUTH_PASS);
/* FALLTHROUGH */
@@ -951,8 +960,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
* Get the "home" directory
*/
sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, ".");
- if(sshc->homedir == NULL) {
+ if(!sshc->homedir) {
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
+ break;
}
data->state.most_recent_ftp_entrypath = sshc->homedir;
@@ -1025,7 +1035,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_SFTP_QUOTE_SETSTAT:
rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
sshc->quote_attrs);
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to set SFTP stats failed: %s",
@@ -1044,7 +1054,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_SFTP_QUOTE_SYMLINK:
rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
sshc->quote_path1);
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "symlink command failed: %s",
@@ -1060,7 +1070,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_SFTP_QUOTE_MKDIR:
rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
(mode_t)data->set.new_directory_perms);
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
failf(data, "mkdir command failed: %s",
ssh_get_error(sshc->ssh_session));
@@ -1075,7 +1085,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_SFTP_QUOTE_RENAME:
rc = sftp_rename(sshc->sftp_session, sshc->quote_path1,
sshc->quote_path2);
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "rename command failed: %s",
@@ -1090,7 +1100,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_SFTP_QUOTE_RMDIR:
rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
failf(data, "rmdir command failed: %s",
ssh_get_error(sshc->ssh_session));
@@ -1104,7 +1114,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_SFTP_QUOTE_UNLINK:
rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
failf(data, "rm command failed: %s",
ssh_get_error(sshc->ssh_session));
@@ -1179,7 +1189,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
sftp_attributes attrs;
attrs = sftp_stat(sshc->sftp_session, protop->path);
- if(attrs != 0) {
+ if(attrs) {
data->info.filetime = attrs->mtime;
sftp_attributes_free(attrs);
}
@@ -1203,16 +1213,17 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
{
int flags;
- if(data->state.resume_from != 0) {
+ if(data->state.resume_from) {
sftp_attributes attrs;
if(data->state.resume_from < 0) {
attrs = sftp_stat(sshc->sftp_session, protop->path);
- if(attrs != 0) {
+ if(attrs) {
curl_off_t size = attrs->size;
if(size < 0) {
failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
+ break;
}
data->state.resume_from = attrs->size;
@@ -1224,7 +1235,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
}
- if(data->set.ftp_append)
+ if(data->set.remote_append)
/* Try to open for append, but create if nonexisting */
flags = O_WRONLY|O_CREAT|O_APPEND;
else if(data->state.resume_from > 0)
@@ -1254,6 +1265,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
else {
MOVE_TO_SFTP_CLOSE_STATE();
+ break;
}
}
@@ -1292,8 +1304,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
CURL_READFUNC_ABORT return code still aborts */
failf(data, "Failed to read data");
MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST);
+ break;
}
} while(passed < data->state.resume_from);
+ if(rc)
+ break;
}
/* now, decrease the size of the read */
@@ -1304,8 +1319,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
- if(rc != 0) {
+ if(rc) {
MOVE_TO_SFTP_CLOSE_STATE();
+ break;
}
}
if(data->state.infilesize > 0) {
@@ -1375,6 +1391,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
(err != SSH_FX_FAILURE) &&
(err != SSH_FX_PERMISSION_DENIED)) {
MOVE_TO_SFTP_CLOSE_STATE();
+ break;
}
rc = 0; /* clear rc and continue */
}
@@ -1398,6 +1415,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
failf(data, "Could not open directory for reading: %s",
ssh_get_error(sshc->ssh_session));
MOVE_TO_SFTP_CLOSE_STATE();
+ break;
}
state(data, SSH_SFTP_READDIR);
break;
@@ -1413,11 +1431,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
sshc->readdir_longentry = sshc->readdir_attrs->longname;
sshc->readdir_len = strlen(sshc->readdir_filename);
- if(data->set.ftp_list_only) {
+ if(data->set.list_only) {
char *tmpLine;
tmpLine = aprintf("%s\n", sshc->readdir_filename);
- if(tmpLine == NULL) {
+ if(!tmpLine) {
state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
@@ -1453,16 +1471,15 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
((sshc->readdir_attrs->permissions & S_IFMT) ==
S_IFLNK)) {
- sshc->readdir_linkPath = malloc(PATH_MAX + 1);
- if(sshc->readdir_linkPath == NULL) {
+ sshc->readdir_linkPath = aprintf("%s%s", protop->path,
+ sshc->readdir_filename);
+
+ if(!sshc->readdir_linkPath) {
state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
- sshc->readdir_filename);
-
state(data, SSH_SFTP_READDIR_LINK);
break;
}
@@ -1492,12 +1509,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
failf(data, "Could not read symlink for reading: %s",
ssh_get_error(sshc->ssh_session));
MOVE_TO_SFTP_CLOSE_STATE();
+ break;
}
- if(sshc->readdir_link_attrs->name == NULL) {
+ if(!sshc->readdir_link_attrs->name) {
sshc->readdir_tmp = sftp_readlink(sshc->sftp_session,
sshc->readdir_linkPath);
- if(sshc->readdir_filename == NULL)
+ if(!sshc->readdir_filename)
sshc->readdir_len = 0;
else
sshc->readdir_len = strlen(sshc->readdir_tmp);
@@ -1587,6 +1605,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
ssh_get_error(sshc->ssh_session));
MOVE_TO_SFTP_CLOSE_STATE();
+ break;
}
state(data, SSH_SFTP_DOWNLOAD_STAT);
@@ -1662,8 +1681,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
rc = sftp_seek64(sshc->sftp_file, from);
- if(rc != 0) {
+ if(rc) {
MOVE_TO_SFTP_CLOSE_STATE();
+ break;
}
}
data->req.size = size;
@@ -1700,8 +1720,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
size - data->state.resume_from);
rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
- if(rc != 0) {
+ if(rc) {
MOVE_TO_SFTP_CLOSE_STATE();
+ break;
}
}
}
@@ -1796,6 +1817,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
failf(data, "SCP requires a known file size for upload");
sshc->actualcode = CURLE_UPLOAD_FAILED;
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
+ break;
}
sshc->scp_session =
@@ -1823,6 +1845,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
err_msg = ssh_get_error(sshc->ssh_session);
failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
+ break;
}
rc = ssh_scp_push_file(sshc->scp_session, protop->path,
@@ -1832,6 +1855,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
err_msg = ssh_get_error(sshc->ssh_session);
failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
+ break;
}
/* upload data */
@@ -1860,6 +1884,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
err_msg = ssh_get_error(sshc->ssh_session);
failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
+ break;
}
state(data, SSH_SCP_DOWNLOAD);
/* FALLTHROUGH */
@@ -2164,7 +2189,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
ssh = &conn->proto.sshc;
ssh->ssh_session = ssh_new();
- if(ssh->ssh_session == NULL) {
+ if(!ssh->ssh_session) {
failf(data, "Failure initialising ssh session");
return CURLE_FAILED_INIT;
}
@@ -2662,7 +2687,7 @@ static void sftp_quote(struct Curl_easy *data)
* command with a space so we can check for it unconditionally
*/
cp = strchr(cmd, ' ');
- if(cp == NULL) {
+ if(!cp) {
failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
@@ -2811,7 +2836,7 @@ static void sftp_quote_stat(struct Curl_easy *data)
if(sshc->quote_attrs)
sftp_attributes_free(sshc->quote_attrs);
sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
- if(sshc->quote_attrs == NULL) {
+ if(!sshc->quote_attrs) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to get SFTP stats failed: %d",
diff --git a/Utilities/cmcurl/lib/vssh/libssh2.c b/Utilities/cmcurl/lib/vssh/libssh2.c
index 3130dcc74..8a6345b94 100644
--- a/Utilities/cmcurl/lib/vssh/libssh2.c
+++ b/Utilities/cmcurl/lib/vssh/libssh2.c
@@ -121,6 +121,7 @@ static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *sock);
static CURLcode ssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
+static void ssh_attach(struct Curl_easy *data, struct connectdata *conn);
/*
* SCP protocol handler.
@@ -142,6 +143,7 @@ const struct Curl_handler Curl_handler_scp = {
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ssh_attach,
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
CURLPROTO_SCP, /* family */
@@ -170,6 +172,7 @@ const struct Curl_handler Curl_handler_sftp = {
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ssh_attach,
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
CURLPROTO_SFTP, /* family */
@@ -184,7 +187,7 @@ kbd_callback(const char *name, int name_len, const char *instruction,
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
void **abstract)
{
- struct connectdata *conn = (struct connectdata *)*abstract;
+ struct Curl_easy *data = (struct Curl_easy *)*abstract;
#ifdef CURL_LIBSSH2_DEBUG
fprintf(stderr, "name=%s\n", name);
@@ -199,11 +202,11 @@ kbd_callback(const char *name, int name_len, const char *instruction,
(void)instruction_len;
#endif /* CURL_LIBSSH2_DEBUG */
if(num_prompts == 1) {
+ struct connectdata *conn = data->conn;
responses[0].text = strdup(conn->passwd);
responses[0].length = curlx_uztoui(strlen(conn->passwd));
}
(void)prompts;
- (void)abstract;
} /* kbd_callback */
static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err)
@@ -956,7 +959,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
out_of_memory = TRUE;
}
- if(out_of_memory || sshc->rsa == NULL) {
+ if(out_of_memory || !sshc->rsa) {
Curl_safefree(sshc->rsa);
Curl_safefree(sshc->rsa_pub);
state(data, SSH_SESSION_FREE);
@@ -1359,7 +1362,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
* command with a space so we can check for it unconditionally
*/
cp = strchr(cmd, ' ');
- if(cp == NULL) {
+ if(!cp) {
failf(data, "Syntax error command '%s'. Missing parameter!",
cmd);
state(data, SSH_SFTP_CLOSE);
@@ -1534,7 +1537,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
+ if(rc && !sshc->acceptfail) { /* get those attributes */
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
@@ -1633,7 +1636,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
@@ -1656,7 +1659,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
@@ -1677,7 +1680,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
failf(data, "mkdir command failed: %s",
@@ -1702,7 +1705,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
@@ -1722,7 +1725,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
failf(data, "rmdir command failed: %s",
@@ -1741,7 +1744,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
@@ -1764,7 +1767,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(rc != 0 && !sshc->acceptfail) {
+ if(rc && !sshc->acceptfail) {
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
failf(data, "statvfs command failed: %s",
@@ -1857,7 +1860,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
* same name as the last directory in the path.
*/
- if(data->state.resume_from != 0) {
+ if(data->state.resume_from) {
LIBSSH2_SFTP_ATTRIBUTES attrs;
if(data->state.resume_from < 0) {
rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
@@ -1880,7 +1883,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
}
- if(data->set.ftp_append)
+ if(data->set.remote_append)
/* Try to open for append, but create if nonexisting */
flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
else if(data->state.resume_from > 0)
@@ -2143,7 +2146,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
readdir_len = (size_t) rc;
sshp->readdir_filename[readdir_len] = '\0';
- if(data->set.ftp_list_only) {
+ if(data->set.list_only) {
result = Curl_client_write(data, CLIENTWRITE_BODY,
sshp->readdir_filename,
readdir_len);
@@ -2931,7 +2934,7 @@ static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
static CURLcode ssh_block_statemach(struct Curl_easy *data,
struct connectdata *conn,
- bool duringconnect)
+ bool disconnect)
{
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
@@ -2945,17 +2948,19 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data,
if(result)
break;
- if(Curl_pgrsUpdate(data))
- return CURLE_ABORTED_BY_CALLBACK;
+ if(!disconnect) {
+ if(Curl_pgrsUpdate(data))
+ return CURLE_ABORTED_BY_CALLBACK;
- result = Curl_speedcheck(data, now);
- if(result)
- break;
+ result = Curl_speedcheck(data, now);
+ if(result)
+ break;
- left = Curl_timeleft(data, NULL, duringconnect);
- if(left < 0) {
- failf(data, "Operation timed out");
- return CURLE_OPERATION_TIMEDOUT;
+ left = Curl_timeleft(data, NULL, FALSE);
+ if(left < 0) {
+ failf(data, "Operation timed out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
}
if(block) {
@@ -3054,17 +3059,15 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
#ifdef CURL_LIBSSH2_DEBUG
curl_socket_t sock;
#endif
- struct SSHPROTO *sshp = data->req.p.ssh;
struct ssh_conn *sshc;
CURLcode result;
struct connectdata *conn = data->conn;
/* initialize per-handle data if not already */
- if(!sshp) {
+ if(!data->req.p.ssh) {
result = ssh_setup_connection(data, conn);
if(result)
return result;
- sshp = data->req.p.ssh;
}
/* We default to persistent connections. We set this already in this connect
@@ -3086,7 +3089,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
my_libssh2_free,
my_libssh2_realloc, data);
- if(sshc->ssh_session == NULL) {
+ if(!sshc->ssh_session) {
failf(data, "Failure initialising ssh session");
return CURLE_FAILED_INIT;
}
@@ -3159,6 +3162,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
if(!sshc->kh) {
libssh2_session_free(sshc->ssh_session);
+ sshc->ssh_session = NULL;
return CURLE_FAILED_INIT;
}
@@ -3279,10 +3283,8 @@ static CURLcode scp_disconnect(struct Curl_easy *data,
if(sshc->ssh_session) {
/* only if there's a session still around to use! */
-
state(data, SSH_SESSION_DISCONNECT);
-
- result = ssh_block_statemach(data, conn, FALSE);
+ result = ssh_block_statemach(data, conn, TRUE);
}
return result;
@@ -3296,10 +3298,9 @@ static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
struct SSHPROTO *sshp = data->req.p.ssh;
struct connectdata *conn = data->conn;
- if(!status) {
+ if(!status)
/* run the state-machine */
result = ssh_block_statemach(data, conn, FALSE);
- }
else
result = status;
@@ -3439,7 +3440,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
if(sshc->ssh_session) {
/* only if there's a session still around to use! */
state(data, SSH_SFTP_SHUTDOWN);
- result = ssh_block_statemach(data, conn, FALSE);
+ result = ssh_block_statemach(data, conn, TRUE);
}
DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
@@ -3606,4 +3607,21 @@ size_t Curl_ssh_version(char *buffer, size_t buflen)
return msnprintf(buffer, buflen, "libssh2/%s", LIBSSH2_VERSION);
}
+/* The SSH session is associated with the *CONNECTION* but the callback user
+ * pointer is an easy handle pointer. This function allows us to reassign the
+ * user pointer to the *CURRENT* (new) easy handle.
+ */
+static void ssh_attach(struct Curl_easy *data, struct connectdata *conn)
+{
+ DEBUGASSERT(data);
+ DEBUGASSERT(conn);
+ if(conn->handler->protocol & PROTO_FAMILY_SSH) {
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ if(sshc->ssh_session) {
+ /* only re-attach if the session already exists */
+ void **abstract = libssh2_session_abstract(sshc->ssh_session);
+ *abstract = data;
+ }
+ }
+}
#endif /* USE_LIBSSH2 */
diff --git a/Utilities/cmcurl/lib/vssh/ssh.h b/Utilities/cmcurl/lib/vssh/ssh.h
index 52e1ee6c2..505b0787c 100644
--- a/Utilities/cmcurl/lib/vssh/ssh.h
+++ b/Utilities/cmcurl/lib/vssh/ssh.h
@@ -263,9 +263,12 @@ extern const struct Curl_handler Curl_handler_sftp;
CURLcode Curl_ssh_init(void);
void Curl_ssh_cleanup(void);
size_t Curl_ssh_version(char *buffer, size_t buflen);
+void Curl_ssh_attach(struct Curl_easy *data,
+ struct connectdata *conn);
#else
/* for non-SSH builds */
#define Curl_ssh_cleanup()
+#define Curl_ssh_attach(x,y)
#endif
#endif /* HEADER_CURL_SSH_H */
diff --git a/Utilities/cmcurl/lib/vssh/wolfssh.c b/Utilities/cmcurl/lib/vssh/wolfssh.c
index 6020180a5..9f3266a24 100644
--- a/Utilities/cmcurl/lib/vssh/wolfssh.c
+++ b/Utilities/cmcurl/lib/vssh/wolfssh.c
@@ -91,6 +91,7 @@ const struct Curl_handler Curl_handler_scp = {
wscp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
@@ -119,6 +120,7 @@ const struct Curl_handler Curl_handler_sftp = {
wsftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
CURLPROTO_SFTP, /* family */
@@ -388,7 +390,7 @@ static CURLcode wssh_connect(struct Curl_easy *data, bool *done)
}
sshc->ssh_session = wolfSSH_new(sshc->ctx);
- if(sshc->ssh_session == NULL) {
+ if(!sshc->ssh_session) {
failf(data, "No wolfSSH session");
goto error;
}
@@ -585,7 +587,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
}
}
- if(data->set.ftp_append)
+ if(data->set.remote_append)
/* Try to open for append, but create if nonexisting */
flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND;
else if(data->state.resume_from > 0)
@@ -859,9 +861,9 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
result = CURLE_OK;
while(name) {
char *line = aprintf("%s\n",
- data->set.ftp_list_only ?
+ data->set.list_only ?
name->fName : name->lName);
- if(line == NULL) {
+ if(!line) {
state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c
index 29b08c0e6..7f729713d 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.c
+++ b/Utilities/cmcurl/lib/vtls/bearssl.c
@@ -300,12 +300,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
-#ifndef CURL_DISABLE_PROXY
- const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- const char *hostname = conn->host.name;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const bool verifyhost = SSL_CONN_CONFIG(verifyhost);
CURLcode ret;
@@ -375,7 +370,8 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
void *session;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, &session, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE,
+ &session, NULL, sockindex)) {
br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
infof(data, "BearSSL: re-using session ID\n");
}
@@ -389,14 +385,14 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
* protocols array in `struct ssl_backend_data`.
*/
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifdef USE_HTTP2
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_PROXY
&& (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
#endif
) {
- backend->protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
- infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ backend->protocols[cur++] = ALPN_H2;
+ infof(data, "ALPN, offering %s\n", ALPN_H2);
}
#endif
@@ -544,8 +540,8 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data,
if(protocol) {
infof(data, "ALPN, server accepted to use %s\n", protocol);
-#ifdef USE_NGHTTP2
- if(!strcmp(protocol, NGHTTP2_PROTO_VERSION_ID))
+#ifdef USE_HTTP2
+ if(!strcmp(protocol, ALPN_H2))
conn->negnpn = CURL_HTTP_VERSION_2;
else
#endif
@@ -571,10 +567,13 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data,
br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
Curl_ssl_sessionid_lock(data);
incache = !(Curl_ssl_getsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
&oldsession, NULL, sockindex));
if(incache)
Curl_ssl_delsessionid(data, oldsession);
- ret = Curl_ssl_addsessionid(data, conn, session, 0, sockindex);
+ ret = Curl_ssl_addsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
+ session, 0, sockindex);
Curl_ssl_sessionid_unlock(data);
if(ret) {
free(session);
@@ -855,6 +854,7 @@ const struct Curl_ssl Curl_ssl_bearssl = {
Curl_none_cert_status_request,
bearssl_connect,
bearssl_connect_nonblocking,
+ Curl_ssl_getsock,
bearssl_get_internals,
bearssl_close,
Curl_none_close_all,
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 9b5f649f7..ca953769d 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -101,8 +101,10 @@
struct ssl_backend_data {
gsk_handle handle;
int iocport;
+#ifndef CURL_DISABLE_PROXY
int localfd;
int remotefd;
+#endif
};
#define BACKEND connssl->backend
@@ -302,8 +304,9 @@ static CURLcode set_callback(struct Curl_easy *data,
static CURLcode set_ciphers(struct Curl_easy *data,
- gsk_handle h, unsigned int *protoflags)
+ gsk_handle h, unsigned int *protoflags)
{
+ struct connectdata *conn = data->conn;
const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
const char *clp;
const struct gskit_cipher *ctp;
@@ -515,6 +518,7 @@ static void close_async_handshake(struct ssl_connect_data *connssl)
static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
int directions)
{
+#ifndef CURL_DISABLE_PROXY
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
fd_set fds_read;
@@ -583,6 +587,9 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
}
return ret; /* OK */
+#else
+ return 0;
+#endif
}
@@ -596,6 +603,7 @@ static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data,
while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
;
BACKEND->handle = (gsk_handle) NULL;
+#ifndef CURL_DISABLE_PROXY
if(BACKEND->localfd >= 0) {
close(BACKEND->localfd);
BACKEND->localfd = -1;
@@ -604,13 +612,14 @@ static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data,
close(BACKEND->remotefd);
BACKEND->remotefd = -1;
}
+#endif
}
if(BACKEND->iocport >= 0)
close_async_handshake(connssl);
}
-static ssize_t gskit_send(struct connectdata *conn, int sockindex,
+static ssize_t gskit_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *curlcode)
{
struct connectdata *conn = data->conn;
@@ -665,6 +674,7 @@ static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf,
static CURLcode
set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
long i = ssl_version;
@@ -700,26 +710,28 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
gsk_handle envir;
CURLcode result;
- int rc;
const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert);
const long int ssl_version = SSL_CONN_CONFIG(version);
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
- conn->host.name;
+ const char * const hostname = SSL_HOST_NAME();
const char *sni;
unsigned int protoflags = 0;
Qso_OverlappedIO_t commarea;
+#ifndef CURL_DISABLE_PROXY
int sockpair[2];
static const int sobufsize = CURL_MAX_WRITE_SIZE;
+#endif
/* Create SSL environment, start (preferably asynchronous) handshake. */
BACKEND->handle = (gsk_handle) NULL;
BACKEND->iocport = -1;
+#ifndef CURL_DISABLE_PROXY
BACKEND->localfd = -1;
BACKEND->remotefd = -1;
+#endif
/* GSKit supports two ways of specifying an SSL context: either by
* application identifier (that should have been defined at the system
@@ -758,6 +770,7 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data,
if(result)
return result;
+#ifndef CURL_DISABLE_PROXY
/* Establish a pipelining socket pair for SSL over SSL. */
if(conn->proxy_ssl[sockindex].use) {
if(Curl_socketpair(0, 0, 0, sockpair))
@@ -775,6 +788,7 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data,
curlx_nonblock(BACKEND->localfd, TRUE);
curlx_nonblock(BACKEND->remotefd, TRUE);
}
+#endif
/* Determine which SSL/TLS version should be enabled. */
sni = hostname;
@@ -827,8 +841,13 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data,
if(!result)
result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
if(!result)
+#ifndef CURL_DISABLE_PROXY
result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
BACKEND->localfd: conn->sock[sockindex]);
+#else
+ result = set_numeric(data, BACKEND->handle, GSK_FD,
+ conn->sock[sockindex]);
+#endif
if(!result)
result = set_ciphers(data, BACKEND->handle, &protoflags);
if(!protoflags) {
@@ -897,10 +916,12 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data,
else if(errno != ENOBUFS)
result = gskit_status(data, GSK_ERROR_IO,
"QsoCreateIOCompletionPort()", 0);
+#ifndef CURL_DISABLE_PROXY
else if(conn->proxy_ssl[sockindex].use) {
/* Cannot pipeline while handshaking synchronously. */
result = CURLE_SSL_CONNECT_ERROR;
}
+#endif
else {
/* No more completion port available. Use synchronous IO. */
result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
@@ -1036,8 +1057,7 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data,
}
/* Check pinned public key. */
- ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ ptr = SSL_PINNED_PUB_KEY();
if(!result && ptr) {
curl_X509certificate x509;
curl_asn1Element *p;
@@ -1159,7 +1179,9 @@ static void gskit_close(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
close_one(&conn->ssl[sockindex], data, conn, sockindex);
+#ifndef CURL_DISABLE_PROXY
close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex);
+#endif
}
@@ -1282,7 +1304,9 @@ const struct Curl_ssl Curl_ssl_gskit = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- NULL /* sha256sum */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#endif /* USE_GSKIT */
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 3ddee1974..ecde5c44d 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -35,14 +35,8 @@
#include <gnutls/abstract.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
-
-#ifdef USE_GNUTLS_NETTLE
#include <gnutls/crypto.h>
-#include <nettle/md5.h>
#include <nettle/sha2.h>
-#else
-#include <gcrypt.h>
-#endif
#include "urldata.h"
#include "sendf.h"
@@ -269,7 +263,7 @@ static CURLcode handshake(struct Curl_easy *data,
strerr = gnutls_alert_get_name(alert);
}
- if(strerr == NULL)
+ if(!strerr)
strerr = gnutls_strerror(rc);
infof(data, "gnutls_handshake() warning: %s\n", strerr);
@@ -283,7 +277,7 @@ static CURLcode handshake(struct Curl_easy *data,
strerr = gnutls_alert_get_name(alert);
}
- if(strerr == NULL)
+ if(!strerr)
strerr = gnutls_strerror(rc);
failf(data, "gnutls_handshake() failed: %s", strerr);
@@ -314,15 +308,29 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
#define GNUTLS_SRP "+SRP"
static CURLcode
-set_ssl_version_min_max(const char **prioritylist, struct Curl_easy *data)
+set_ssl_version_min_max(struct Curl_easy *data,
+ const char **prioritylist,
+ const char *tls13support)
{
struct connectdata *conn = data->conn;
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
- if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
+ if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
+ (ssl_version == CURL_SSLVERSION_TLSv1))
+ ssl_version = CURL_SSLVERSION_TLSv1_0;
+ if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
+ if(!tls13support) {
+ /* If the running GnuTLS doesn't support TLS 1.3, we must not specify a
+ prioritylist involving that since it will make GnuTLS return an en
+ error back at us */
+ if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
+ (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ }
}
+
switch(ssl_version | ssl_version_max) {
case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
@@ -401,6 +409,7 @@ gtls_connect_step1(struct Curl_easy *data,
const char *err = NULL;
const char * const hostname = SSL_HOST_NAME();
long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
+ const char *tls13support;
if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
@@ -548,36 +557,34 @@ gtls_connect_step1(struct Curl_easy *data,
if(rc != GNUTLS_E_SUCCESS)
return CURLE_SSL_CONNECT_ERROR;
+ /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
+ tls13support = gnutls_check_version("3.6.5");
+
/* Ensure +SRP comes at the *end* of all relevant strings so that it can be
* removed if a run-time error indicates that SRP is not supported by this
* GnuTLS version */
switch(SSL_CONN_CONFIG(version)) {
- case CURL_SSLVERSION_SSLv3:
- prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
- break;
+ case CURL_SSLVERSION_TLSv1_3:
+ if(!tls13support) {
+ failf(data, "This GnuTLS installation does not support TLS 1.3");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* FALLTHROUGH */
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0"
-#ifdef HAS_TLS13
- ":+VERS-TLS1.3"
-#endif
- ;
- break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_3:
- {
- CURLcode result = set_ssl_version_min_max(&prioritylist, data);
- if(result != CURLE_OK)
- return result;
- break;
- }
+ case CURL_SSLVERSION_TLSv1_2: {
+ CURLcode result = set_ssl_version_min_max(data, &prioritylist,
+ tls13support);
+ if(result)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv2:
- failf(data, "GnuTLS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_SSLv3:
default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ failf(data, "GnuTLS does not support SSLv2 or SSLv3");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -592,7 +599,6 @@ gtls_connect_step1(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
strcpy(prioritysrp, prioritylist);
strcpy(prioritysrp + len, ":" GNUTLS_SRP);
-
rc = gnutls_priority_set_direct(session, prioritysrp, &err);
free(prioritysrp);
@@ -617,16 +623,16 @@ gtls_connect_step1(struct Curl_easy *data,
int cur = 0;
gnutls_datum_t protocols[2];
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifdef USE_HTTP2
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_PROXY
&& (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
#endif
) {
- protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
- protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
+ protocols[cur].data = (unsigned char *)ALPN_H2;
+ protocols[cur].size = ALPN_H2_LENGTH;
cur++;
- infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ infof(data, "ALPN, offering %.*s\n", ALPN_H2_LENGTH, ALPN_H2);
}
#endif
@@ -733,6 +739,7 @@ gtls_connect_step1(struct Curl_easy *data,
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
&ssl_sessionid, &ssl_idsize, sockindex)) {
/* we got a session id, use it! */
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
@@ -1183,8 +1190,7 @@ gtls_connect_step3(struct Curl_easy *data,
infof(data, "\t server certificate activation date OK\n");
}
- ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ ptr = SSL_PINNED_PUB_KEY();
if(ptr) {
result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
if(result != CURLE_OK) {
@@ -1248,10 +1254,10 @@ gtls_connect_step3(struct Curl_easy *data,
infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
proto.data);
-#ifdef USE_NGHTTP2
- if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
- !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
- NGHTTP2_PROTO_VERSION_ID_LEN)) {
+#ifdef USE_HTTP2
+ if(proto.size == ALPN_H2_LENGTH &&
+ !memcmp(ALPN_H2, proto.data,
+ ALPN_H2_LENGTH)) {
conn->negnpn = CURL_HTTP_VERSION_2;
}
else
@@ -1292,8 +1298,9 @@ gtls_connect_step3(struct Curl_easy *data,
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL,
- sockindex));
+ incache = !(Curl_ssl_getsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
+ &ssl_sessionid, NULL, sockindex));
if(incache) {
/* there was one before in the cache, so instead of risking that the
previous one was rejected, we just kill that and store the new */
@@ -1301,8 +1308,10 @@ gtls_connect_step3(struct Curl_easy *data,
}
/* store this session id */
- result = Curl_ssl_addsessionid(data, conn, connect_sessionid,
- connect_idsize, sockindex);
+ result = Curl_ssl_addsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
+ connect_sessionid, connect_idsize,
+ sockindex);
Curl_ssl_sessionid_unlock(data);
if(result) {
free(connect_sessionid);
@@ -1583,39 +1592,14 @@ static size_t gtls_version(char *buffer, size_t size)
return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
}
-#ifndef USE_GNUTLS_NETTLE
-static int gtls_seed(struct Curl_easy *data)
-{
- /* we have the "SSL is seeded" boolean static to prevent multiple
- time-consuming seedings in vain */
- static bool ssl_seeded = FALSE;
-
- /* Quickly add a bit of entropy */
- gcry_fast_random_poll();
-
- if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
- data->set.str[STRING_SSL_EGDSOCKET]) {
- ssl_seeded = TRUE;
- }
- return 0;
-}
-#endif
-
/* data might be NULL! */
static CURLcode gtls_random(struct Curl_easy *data,
unsigned char *entropy, size_t length)
{
-#if defined(USE_GNUTLS_NETTLE)
int rc;
(void)data;
rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
return rc?CURLE_FAILED_INIT:CURLE_OK;
-#elif defined(USE_GNUTLS)
- if(data)
- gtls_seed(data); /* Initiate the seed if not already done */
- gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
-#endif
- return CURLE_OK;
}
static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
@@ -1623,18 +1607,10 @@ static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
unsigned char *sha256sum, /* output */
size_t sha256len)
{
-#if defined(USE_GNUTLS_NETTLE)
struct sha256_ctx SHA256pw;
sha256_init(&SHA256pw);
sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
-#elif defined(USE_GNUTLS)
- gcry_md_hd_t SHA256pw;
- gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
- gcry_md_write(SHA256pw, tmp, tmplen);
- memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
- gcry_md_close(SHA256pw);
-#endif
return CURLE_OK;
}
@@ -1671,6 +1647,7 @@ const struct Curl_ssl Curl_ssl_gnutls = {
gtls_cert_status_request, /* cert_status_request */
gtls_connect, /* connect */
gtls_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
gtls_get_internals, /* get_internals */
gtls_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1679,7 +1656,9 @@ const struct Curl_ssl Curl_ssl_gnutls = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- gtls_sha256sum /* sha256sum */
+ gtls_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#endif /* USE_GNUTLS */
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index fc3a948d1..3a0be0f04 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -251,22 +251,16 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
-#else
- const char * const hostname = conn->host.name;
- const long int port = conn->remote_port;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
+ const long int port = SSL_HOST_PORT();
int ret = -1;
char errorbuf[128];
errorbuf[0] = 0;
- /* mbedTLS only supports SSLv3 and TLSv1 */
- if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
- failf(data, "mbedTLS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
+ if((SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) ||
+ (SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)) {
+ failf(data, "Not supported SSL version");
+ return CURLE_NOT_BUILT_IN;
}
#ifdef THREADING_SUPPORT
@@ -414,13 +408,6 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
MBEDTLS_SSL_MINOR_VERSION_1);
infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
break;
- case CURL_SSLVERSION_SSLv3:
- mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_0);
- mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_0);
- infof(data, "mbedTLS: Set SSL version to SSLv3\n");
- break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
@@ -463,7 +450,9 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
void *old_session = NULL;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, &old_session, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
+ &old_session, NULL, sockindex)) {
ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
if(ret) {
Curl_ssl_sessionid_unlock(data);
@@ -495,7 +484,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
if(conn->bits.tls_enable_alpn) {
const char **p = &backend->protocols[0];
#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2)
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2)
*p++ = NGHTTP2_PROTO_VERSION_ID;
#endif
*p++ = ALPN_HTTP_1_1;
@@ -547,14 +536,7 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const mbedtls_x509_crt *peercert;
-#ifndef CURL_DISABLE_PROXY
- const char * const pinnedpubkey = SSL_IS_PROXY() ?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-#else
- const char * const pinnedpubkey =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-#endif
+ const char * const pinnedpubkey = SSL_PINNED_PUB_KEY();
conn->recv[sockindex] = mbed_recv;
conn->send[sockindex] = mbed_send;
@@ -724,6 +706,7 @@ mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn,
int ret;
mbedtls_ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
+ bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session));
if(!our_ssl_sessionid)
@@ -742,11 +725,12 @@ mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn,
/* If there's already a matching session in the cache, delete it */
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, sockindex))
+ if(!Curl_ssl_getsessionid(data, conn, isproxy, &old_ssl_sessionid, NULL,
+ sockindex))
Curl_ssl_delsessionid(data, old_ssl_sessionid);
- retcode = Curl_ssl_addsessionid(data, conn,
- our_ssl_sessionid, 0, sockindex);
+ retcode = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid,
+ 0, sockindex);
Curl_ssl_sessionid_unlock(data);
if(retcode) {
mbedtls_ssl_session_free(our_ssl_sessionid);
@@ -1100,6 +1084,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
Curl_none_cert_status_request, /* cert_status_request */
mbedtls_connect, /* connect */
mbedtls_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
mbedtls_get_internals, /* get_internals */
mbedtls_close, /* close_one */
mbedtls_close_all, /* close_all */
@@ -1108,7 +1093,9 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- mbedtls_sha256sum /* sha256sum */
+ mbedtls_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#endif /* USE_MBEDTLS */
diff --git a/Utilities/cmcurl/lib/vtls/mesalink.c b/Utilities/cmcurl/lib/vtls/mesalink.c
index b6d1005ec..bf8600d32 100644
--- a/Utilities/cmcurl/lib/vtls/mesalink.c
+++ b/Utilities/cmcurl/lib/vtls/mesalink.c
@@ -98,8 +98,7 @@ mesalink_connect_step1(struct Curl_easy *data,
#ifdef ENABLE_IPV6
struct in6_addr addr6;
#endif
- const char *const hostname =
- SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name;
+ const char * const hostname = SSL_HOST_NAME();
size_t hostname_len = strlen(hostname);
SSL_METHOD *req_method = NULL;
@@ -261,7 +260,9 @@ mesalink_connect_step1(struct Curl_easy *data,
void *ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
+ &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
Curl_ssl_sessionid_unlock(data);
@@ -345,13 +346,14 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
bool incache;
SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
+ bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
our_ssl_sessionid = SSL_get_session(BACKEND->handle);
Curl_ssl_sessionid_lock(data);
incache =
- !(Curl_ssl_getsessionid(data, conn,
- &old_ssl_sessionid, NULL, sockindex));
+ !(Curl_ssl_getsessionid(data, conn, isproxy, &old_ssl_sessionid, NULL,
+ sockindex));
if(incache) {
if(old_ssl_sessionid != our_ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing\n");
@@ -361,8 +363,9 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
}
if(!incache) {
- result = Curl_ssl_addsessionid(
- data, conn, our_ssl_sessionid, 0 /* unknown size */, sockindex);
+ result =
+ Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid, 0,
+ sockindex);
if(result) {
Curl_ssl_sessionid_unlock(data);
failf(data, "failed to store ssl session");
@@ -654,6 +657,7 @@ const struct Curl_ssl Curl_ssl_mesalink = {
Curl_none_cert_status_request, /* cert_status_request */
mesalink_connect, /* connect */
mesalink_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
mesalink_get_internals, /* get_internals */
mesalink_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -662,7 +666,9 @@ const struct Curl_ssl Curl_ssl_mesalink = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- NULL /* sha256sum */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#endif
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index e5ab71cdf..1582b1e58 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -139,9 +139,15 @@ static const struct cipher_s cipherlist[] = {
{"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA},
{"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA},
{"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA},
+ {"dhe_rsa_3des_sha", SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"dhe_dss_3des_sha", SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA},
+ {"dhe_rsa_des_sha", SSL_DHE_RSA_WITH_DES_CBC_SHA},
+ {"dhe_dss_des_sha", SSL_DHE_DSS_WITH_DES_CBC_SHA},
/* TLS 1.0: Exportable 56-bit Cipher Suites. */
{"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
{"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
+ /* Ephemeral DH with RC4 bulk encryption */
+ {"dhe_dss_rc4_128_sha", TLS_DHE_DSS_WITH_RC4_128_SHA},
/* AES ciphers. */
{"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA},
{"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA},
@@ -219,6 +225,25 @@ static const struct cipher_s cipherlist[] = {
{"aes_256_gcm_sha_384", TLS_AES_256_GCM_SHA384},
{"chacha20_poly1305_sha_256", TLS_CHACHA20_POLY1305_SHA256},
#endif
+#ifdef TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
+ /* AES CBC cipher suites in RFC 5246. Introduced in NSS release 3.20 */
+ {"dhe_dss_aes_128_sha_256", TLS_DHE_DSS_WITH_AES_128_CBC_SHA256},
+ {"dhe_dss_aes_256_sha_256", TLS_DHE_DSS_WITH_AES_256_CBC_SHA256},
+#endif
+#ifdef TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ /* Camellia cipher suites in RFC 4132/5932.
+ Introduced in NSS release 3.12 */
+ {"dhe_rsa_camellia_128_sha", TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA},
+ {"dhe_dss_camellia_128_sha", TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA},
+ {"dhe_rsa_camellia_256_sha", TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA},
+ {"dhe_dss_camellia_256_sha", TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA},
+ {"rsa_camellia_128_sha", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA},
+ {"rsa_camellia_256_sha", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA},
+#endif
+#ifdef TLS_RSA_WITH_SEED_CBC_SHA
+ /* SEED cipher suite in RFC 4162. Introduced in NSS release 3.12.3 */
+ {"rsa_seed_sha", TLS_RSA_WITH_SEED_CBC_SHA},
+#endif
};
#if defined(WIN32)
@@ -312,7 +337,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
while((*cipher) && (ISSPACE(*cipher)))
++cipher;
- cipher_list = strchr(cipher, ',');
+ cipher_list = strpbrk(cipher, ":, ");
if(cipher_list) {
*cipher_list++ = '\0';
}
@@ -380,7 +405,7 @@ static int is_file(const char *filename)
{
struct_stat st;
- if(filename == NULL)
+ if(!filename)
return 0;
if(stat(filename, &st) == 0)
@@ -542,7 +567,6 @@ static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
if(!result && !cacert) {
/* we have successfully loaded a client certificate */
- CERTCertificate *cert;
char *nickname = NULL;
char *n = strrchr(filename, '/');
if(n)
@@ -554,7 +578,7 @@ static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
* <https://bugzilla.redhat.com/733685>. */
nickname = aprintf("PEM Token #1:%s", n);
if(nickname) {
- cert = PK11_FindCertFromNickname(nickname, NULL);
+ CERTCertificate *cert = PK11_FindCertFromNickname(nickname, NULL);
if(cert)
CERT_DestroyCertificate(cert);
@@ -846,8 +870,8 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
}
#ifdef USE_NGHTTP2
- if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN &&
- !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) {
+ if(buflen == ALPN_H2_LENGTH &&
+ !memcmp(ALPN_H2, buf, ALPN_H2_LENGTH)) {
conn->negnpn = CURL_HTTP_VERSION_2;
}
else
@@ -957,7 +981,6 @@ static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock)
CERTCertificate *cert2;
CERTCertificate *cert3;
PRTime now;
- int i;
if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) ==
SECSuccess && channel.length == sizeof(channel) &&
@@ -978,8 +1001,8 @@ static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock)
}
else {
/* Count certificates in chain. */
+ int i = 1;
now = PR_Now();
- i = 1;
if(!cert->isRoot) {
cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
while(cert2) {
@@ -1425,7 +1448,7 @@ static CURLcode nss_setup(struct Curl_easy *data)
static int nss_init(void)
{
/* curl_global_init() is not thread-safe so this test is ok */
- if(nss_initlock == NULL) {
+ if(!nss_initlock) {
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
nss_initlock = PR_NewLock();
nss_crllock = PR_NewLock();
@@ -1701,8 +1724,7 @@ static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version)
return CURLE_OK;
case CURL_SSLVERSION_SSLv3:
- *nssver = SSL_LIBRARY_VERSION_3_0;
- return CURLE_OK;
+ return CURLE_NOT_BUILT_IN;
case CURL_SSLVERSION_TLSv1_0:
*nssver = SSL_LIBRARY_VERSION_TLS_1_0;
@@ -1782,12 +1804,11 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
struct Curl_easy *data,
CURLcode curlerr)
{
- PRErrorCode err = 0;
struct ssl_backend_data *backend = connssl->backend;
if(is_nss_error(curlerr)) {
/* read NSPR error code */
- err = PR_GetError();
+ PRErrorCode err = PR_GetError();
if(is_cc_error(err))
curlerr = CURLE_SSL_CERTPROBLEM;
@@ -1809,7 +1830,7 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
struct Curl_easy *data,
bool blocking)
{
- static PRSocketOptionData sock_opt;
+ PRSocketOptionData sock_opt;
struct ssl_backend_data *backend = connssl->backend;
sock_opt.option = PR_SockOpt_Nonblocking;
sock_opt.value.non_blocking = !blocking;
@@ -2082,16 +2103,15 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
int cur = 0;
unsigned char protocols[128];
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifdef USE_HTTP2
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_PROXY
&& (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
#endif
) {
- protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN;
- memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID,
- NGHTTP2_PROTO_VERSION_ID_LEN);
- cur += NGHTTP2_PROTO_VERSION_ID_LEN;
+ protocols[cur++] = ALPN_H2_LENGTH;
+ memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
+ cur += ALPN_H2_LENGTH;
}
#endif
protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
@@ -2435,6 +2455,7 @@ const struct Curl_ssl Curl_ssl_nss = {
nss_cert_status_request, /* cert_status_request */
nss_connect, /* connect */
nss_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
nss_get_internals, /* get_internals */
nss_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -2444,7 +2465,9 @@ const struct Curl_ssl Curl_ssl_nss = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
nss_false_start, /* false_start */
- nss_sha256sum /* sha256sum */
+ nss_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#endif /* USE_NSS */
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 784d9f70e..ebd7abc3b 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -122,12 +122,6 @@
#define HAVE_ERR_REMOVE_THREAD_STATE 1
#endif
-#if !defined(HAVE_SSLV2_CLIENT_METHOD) || \
- OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0+ has no SSLv2 */
-#undef OPENSSL_NO_SSL2 /* undef first to avoid compiler warnings */
-#define OPENSSL_NO_SSL2
-#endif
-
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \
!(defined(LIBRESSL_VERSION_NUMBER) && \
LIBRESSL_VERSION_NUMBER < 0x20700000L)
@@ -234,6 +228,8 @@
#endif
struct ssl_backend_data {
+ struct Curl_easy *logger; /* transfer handle to pass trace logs to, only
+ using sockindex 0 */
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
@@ -244,6 +240,10 @@ struct ssl_backend_data {
#endif
};
+static void ossl_associate_connection(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex);
+
/*
* Number of bytes to read from the random number seed file. This must be
* a finite value (because some entropy "files" like /dev/urandom have
@@ -391,12 +391,23 @@ static int ossl_get_ssl_conn_index(void)
*/
static int ossl_get_ssl_sockindex_index(void)
{
- static int ssl_ex_data_sockindex_index = -1;
- if(ssl_ex_data_sockindex_index < 0) {
- ssl_ex_data_sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL,
- NULL);
+ static int sockindex_index = -1;
+ if(sockindex_index < 0) {
+ sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ }
+ return sockindex_index;
+}
+
+/* Return an extra data index for proxy boolean.
+ * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
+ */
+static int ossl_get_proxy_index(void)
+{
+ static int proxy_index = -1;
+ if(proxy_index < 0) {
+ proxy_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
}
- return ssl_ex_data_sockindex_index;
+ return proxy_index;
}
static int passwd_callback(char *buf, int num, int encrypting,
@@ -587,11 +598,16 @@ static bool is_pkcs11_uri(const char *string)
static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine);
static int
-SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type,
- const char *key_passwd)
+SSL_CTX_use_certificate_blob(SSL_CTX *ctx, const struct curl_blob *blob,
+ int type, const char *key_passwd)
{
int ret = 0;
X509 *x = NULL;
+ /* the typecast of blob->len is fine since it is guaranteed to never be
+ larger than CURL_MAX_INPUT_LENGTH */
+ BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len));
+ if(!in)
+ return CURLE_OUT_OF_MEMORY;
if(type == SSL_FILETYPE_ASN1) {
/* j = ERR_R_ASN1_LIB; */
@@ -607,7 +623,7 @@ SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type,
goto end;
}
- if(x == NULL) {
+ if(!x) {
ret = 0;
goto end;
}
@@ -615,15 +631,19 @@ SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type,
ret = SSL_CTX_use_certificate(ctx, x);
end:
X509_free(x);
+ BIO_free(in);
return ret;
}
static int
-SSL_CTX_use_PrivateKey_bio(SSL_CTX *ctx, BIO* in, int type,
- const char *key_passwd)
+SSL_CTX_use_PrivateKey_blob(SSL_CTX *ctx, const struct curl_blob *blob,
+ int type, const char *key_passwd)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
+ BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len));
+ if(!in)
+ return CURLE_OUT_OF_MEMORY;
if(type == SSL_FILETYPE_PEM)
pkey = PEM_read_bio_PrivateKey(in, NULL, passwd_callback,
@@ -634,19 +654,20 @@ SSL_CTX_use_PrivateKey_bio(SSL_CTX *ctx, BIO* in, int type,
ret = 0;
goto end;
}
- if(pkey == NULL) {
+ if(!pkey) {
ret = 0;
goto end;
}
ret = SSL_CTX_use_PrivateKey(ctx, pkey);
EVP_PKEY_free(pkey);
end:
+ BIO_free(in);
return ret;
}
static int
-SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in,
- const char *key_passwd)
+SSL_CTX_use_certificate_chain_blob(SSL_CTX *ctx, const struct curl_blob *blob,
+ const char *key_passwd)
{
/* SSL_CTX_add1_chain_cert introduced in OpenSSL 1.0.2 */
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* OpenSSL 1.0.2 or later */ \
@@ -655,13 +676,16 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in,
int ret = 0;
X509 *x = NULL;
void *passwd_callback_userdata = (void *)key_passwd;
+ BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len));
+ if(!in)
+ return CURLE_OUT_OF_MEMORY;
ERR_clear_error();
x = PEM_read_bio_X509_AUX(in, NULL,
passwd_callback, (void *)key_passwd);
- if(x == NULL) {
+ if(!x) {
ret = 0;
goto end;
}
@@ -669,7 +693,7 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in,
ret = SSL_CTX_use_certificate(ctx, x);
if(ERR_peek_error() != 0)
- ret = 0;
+ ret = 0;
if(ret) {
X509 *ca;
@@ -701,10 +725,11 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in,
end:
X509_free(x);
+ BIO_free(in);
return ret;
#else
(void)ctx; /* unused */
- (void)in; /* unused */
+ (void)blob; /* unused */
(void)key_passwd; /* unused */
return 0;
#endif
@@ -714,10 +739,10 @@ static
int cert_stuff(struct Curl_easy *data,
SSL_CTX* ctx,
char *cert_file,
- BIO *cert_bio,
+ const struct curl_blob *cert_blob,
const char *cert_type,
char *key_file,
- BIO* key_bio,
+ const struct curl_blob *key_blob,
const char *key_type,
char *key_passwd)
{
@@ -726,7 +751,7 @@ int cert_stuff(struct Curl_easy *data,
int file_type = do_file_type(cert_type);
- if(cert_file || cert_bio || (file_type == SSL_FILETYPE_ENGINE)) {
+ if(cert_file || cert_blob || (file_type == SSL_FILETYPE_ENGINE)) {
SSL *ssl;
X509 *x509;
int cert_done = 0;
@@ -743,9 +768,9 @@ int cert_stuff(struct Curl_easy *data,
switch(file_type) {
case SSL_FILETYPE_PEM:
/* SSL_CTX_use_certificate_chain_file() only works on PEM files */
- cert_use_result = cert_bio ?
- SSL_CTX_use_certificate_chain_bio(ctx, cert_bio, key_passwd) :
- SSL_CTX_use_certificate_chain_file(ctx, cert_file);
+ cert_use_result = cert_blob ?
+ SSL_CTX_use_certificate_chain_blob(ctx, cert_blob, key_passwd) :
+ SSL_CTX_use_certificate_chain_file(ctx, cert_file);
if(cert_use_result != 1) {
failf(data,
"could not load PEM client certificate, " OSSL_PACKAGE
@@ -762,10 +787,10 @@ int cert_stuff(struct Curl_easy *data,
we use the case above for PEM so this can only be performed with
ASN1 files. */
- cert_use_result = cert_bio ?
- SSL_CTX_use_certificate_bio(ctx, cert_bio,
- file_type, key_passwd) :
- SSL_CTX_use_certificate_file(ctx, cert_file, file_type);
+ cert_use_result = cert_blob ?
+ SSL_CTX_use_certificate_blob(ctx, cert_blob,
+ file_type, key_passwd) :
+ 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
@@ -842,13 +867,24 @@ int cert_stuff(struct Curl_easy *data,
case SSL_FILETYPE_PKCS12:
{
- BIO *fp = NULL;
+ BIO *cert_bio = NULL;
PKCS12 *p12 = NULL;
EVP_PKEY *pri;
STACK_OF(X509) *ca = NULL;
- if(!cert_bio) {
- fp = BIO_new(BIO_s_file());
- if(fp == NULL) {
+ if(cert_blob) {
+ cert_bio = BIO_new_mem_buf(cert_blob->data, (int)(cert_blob->len));
+ if(!cert_bio) {
+ failf(data,
+ "BIO_new_mem_buf NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ return 0;
+ }
+ }
+ else {
+ cert_bio = BIO_new(BIO_s_file());
+ if(!cert_bio) {
failf(data,
"BIO_new return NULL, " OSSL_PACKAGE
" error %s",
@@ -857,20 +893,19 @@ int cert_stuff(struct Curl_easy *data,
return 0;
}
- if(BIO_read_filename(fp, cert_file) <= 0) {
+ if(BIO_read_filename(cert_bio, cert_file) <= 0) {
failf(data, "could not open PKCS12 file '%s'", cert_file);
- BIO_free(fp);
+ BIO_free(cert_bio);
return 0;
}
}
- p12 = d2i_PKCS12_bio(cert_bio ? cert_bio : fp, NULL);
- if(fp)
- BIO_free(fp);
+ p12 = d2i_PKCS12_bio(cert_bio, NULL);
+ BIO_free(cert_bio);
if(!p12) {
failf(data, "error reading PKCS12 file '%s'",
- cert_bio ? "(memory blob)" : cert_file);
+ cert_blob ? "(memory blob)" : cert_file);
return 0;
}
@@ -951,9 +986,9 @@ int cert_stuff(struct Curl_easy *data,
return 0;
}
- if((!key_file) && (!key_bio)) {
+ if((!key_file) && (!key_blob)) {
key_file = cert_file;
- key_bio = cert_bio;
+ key_blob = cert_blob;
}
else
file_type = do_file_type(key_type);
@@ -964,8 +999,8 @@ int cert_stuff(struct Curl_easy *data,
break;
/* FALLTHROUGH */
case SSL_FILETYPE_ASN1:
- cert_use_result = key_bio ?
- SSL_CTX_use_PrivateKey_bio(ctx, key_bio, file_type, key_passwd) :
+ cert_use_result = key_blob ?
+ SSL_CTX_use_PrivateKey_blob(ctx, key_blob, file_type, key_passwd) :
SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type);
if(cert_use_result != 1) {
failf(data, "unable to set private key file: '%s' type %s",
@@ -1172,7 +1207,7 @@ static int ossl_init(void)
/* Initialize the extra data indexes */
if(ossl_get_ssl_data_index() < 0 || ossl_get_ssl_conn_index() < 0 ||
- ossl_get_ssl_sockindex_index() < 0)
+ ossl_get_ssl_sockindex_index() < 0 || ossl_get_proxy_index() < 0)
return 0;
return 1;
@@ -1356,10 +1391,16 @@ static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
return list;
}
-static void ossl_closeone(struct ssl_connect_data *connssl)
+#define set_logger(conn, data) \
+ conn->ssl[0].backend->logger = data
+
+static void ossl_closeone(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct ssl_connect_data *connssl)
{
struct ssl_backend_data *backend = connssl->backend;
if(backend->handle) {
+ set_logger(conn, data);
(void)SSL_shutdown(backend->handle);
SSL_set_connect_state(backend->handle);
@@ -1378,10 +1419,9 @@ static void ossl_closeone(struct ssl_connect_data *connssl)
static void ossl_close(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
- (void) data;
- ossl_closeone(&conn->ssl[sockindex]);
+ ossl_closeone(data, conn, &conn->ssl[sockindex]);
#ifndef CURL_DISABLE_PROXY
- ossl_closeone(&conn->proxy_ssl[sockindex]);
+ ossl_closeone(data, conn, &conn->proxy_ssl[sockindex]);
#endif
}
@@ -2055,25 +2095,24 @@ static const char *tls_rt_type(int type)
}
}
-
/*
* Our callback from the SSL/TLS layers.
*/
-static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
- const void *buf, size_t len, SSL *ssl,
- void *userp)
+static void ossl_trace(int direction, int ssl_ver, int content_type,
+ const void *buf, size_t len, SSL *ssl,
+ void *userp)
{
- struct Curl_easy *data;
char unknown[32];
const char *verstr = NULL;
struct connectdata *conn = userp;
+ struct ssl_connect_data *connssl = &conn->ssl[0];
+ struct ssl_backend_data *backend = connssl->backend;
+ struct Curl_easy *data = backend->logger;
- if(!conn || !conn->data || !conn->data->set.fdebug ||
+ if(!conn || !data || !data->set.fdebug ||
(direction != 0 && direction != 1))
return;
- data = conn->data;
-
switch(ssl_ver) {
#ifdef SSL2_VERSION /* removed in recent versions */
case SSL2_VERSION:
@@ -2221,12 +2260,10 @@ select_next_proto_cb(SSL *ssl,
struct connectdata *conn = data->conn;
(void)ssl;
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
- !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID,
- NGHTTP2_PROTO_VERSION_ID_LEN)) {
- infof(data, "NPN, negotiated HTTP2 (%s)\n",
- NGHTTP2_PROTO_VERSION_ID);
+#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)\n", ALPN_H2);
conn->negnpn = CURL_HTTP_VERSION_2;
return SSL_TLSEXT_ERR_OK;
}
@@ -2248,35 +2285,6 @@ select_next_proto_cb(SSL *ssl,
}
#endif /* HAS_NPN */
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
-static const char *
-get_ssl_version_txt(SSL *ssl)
-{
- if(!ssl)
- return "";
-
- switch(SSL_version(ssl)) {
-#ifdef TLS1_3_VERSION
- case TLS1_3_VERSION:
- return "TLSv1.3";
-#endif
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- case TLS1_2_VERSION:
- return "TLSv1.2";
- case TLS1_1_VERSION:
- return "TLSv1.1";
-#endif
- case TLS1_VERSION:
- return "TLSv1.0";
- case SSL3_VERSION:
- return "SSLv3";
- case SSL2_VERSION:
- return "SSLv2";
- }
- return "unknown";
-}
-#endif
-
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
static CURLcode
set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
@@ -2455,8 +2463,10 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
int data_idx = ossl_get_ssl_data_index();
int connectdata_idx = ossl_get_ssl_conn_index();
int sockindex_idx = ossl_get_ssl_sockindex_index();
+ int proxy_idx = ossl_get_proxy_index();
+ bool isproxy;
- if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0)
+ if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0 || proxy_idx < 0)
return 0;
conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx);
@@ -2469,13 +2479,18 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
sockindex = (int)(sockindex_ptr - conn->sock);
+ isproxy = SSL_get_ex_data(ssl, proxy_idx) ? TRUE : FALSE;
+
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
void *old_ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL,
- sockindex));
+ if(isproxy)
+ incache = FALSE;
+ else
+ incache = !(Curl_ssl_getsessionid(data, conn, isproxy,
+ &old_ssl_sessionid, NULL, sockindex));
if(incache) {
if(old_ssl_sessionid != ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing\n");
@@ -2485,8 +2500,8 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
}
if(!incache) {
- if(!Curl_ssl_addsessionid(data, conn, ssl_sessionid,
- 0 /* unknown size */, sockindex)) {
+ if(!Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid,
+ 0 /* unknown size */, sockindex)) {
/* the session has been put into the session cache */
res = 1;
}
@@ -2499,6 +2514,67 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
return res;
}
+static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+ const struct curl_blob *ca_info_blob)
+{
+ /* these need freed at the end */
+ BIO *cbio = NULL;
+ STACK_OF(X509_INFO) *inf = NULL;
+
+ /* everything else is just a reference */
+ int i, count = 0;
+ X509_STORE *cts = NULL;
+ X509_INFO *itmp = NULL;
+
+ if(ca_info_blob->len > (size_t)INT_MAX)
+ return CURLE_SSL_CACERT_BADFILE;
+
+ cts = SSL_CTX_get_cert_store(ctx);
+ if(!cts)
+ return CURLE_OUT_OF_MEMORY;
+
+ cbio = BIO_new_mem_buf(ca_info_blob->data, (int)ca_info_blob->len);
+ if(!cbio)
+ return CURLE_OUT_OF_MEMORY;
+
+ inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);
+ if(!inf) {
+ BIO_free(cbio);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+
+ /* add each entry from PEM file to x509_store */
+ for(i = 0; i < (int)sk_X509_INFO_num(inf); ++i) {
+ itmp = sk_X509_INFO_value(inf, i);
+ if(itmp->x509) {
+ if(X509_STORE_add_cert(cts, itmp->x509)) {
+ ++count;
+ }
+ else {
+ /* set count to 0 to return an error */
+ count = 0;
+ break;
+ }
+ }
+ if(itmp->crl) {
+ if(X509_STORE_add_crl(cts, itmp->crl)) {
+ ++count;
+ }
+ else {
+ /* set count to 0 to return an error */
+ count = 0;
+ break;
+ }
+ }
+ }
+
+ sk_X509_INFO_pop_free(inf, X509_INFO_free);
+ BIO_free(cbio);
+
+ /* if we didn't end up importing anything, treat that as an error */
+ return (count > 0 ? CURLE_OK : CURLE_SSL_CACERT_BADFILE);
+}
+
static CURLcode ossl_connect_step1(struct Curl_easy *data,
struct connectdata *conn, int sockindex)
{
@@ -2509,6 +2585,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
ctx_option_t ctx_options = 0;
+ void *ssl_sessionid = NULL;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
bool sni;
@@ -2526,8 +2603,11 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
+ const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
- const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const char * const ssl_cafile =
+ /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+ (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
@@ -2562,31 +2642,11 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
use_sni(TRUE);
break;
case CURL_SSLVERSION_SSLv2:
-#ifdef OPENSSL_NO_SSL2
- failf(data, OSSL_PACKAGE " was built without SSLv2 support");
+ failf(data, "No SSLv2 support");
return CURLE_NOT_BUILT_IN;
-#else
-#ifdef USE_OPENSSL_SRP
- if(ssl_authtype == CURL_TLSAUTH_SRP)
- return CURLE_SSL_CONNECT_ERROR;
-#endif
- req_method = SSLv2_client_method();
- use_sni(FALSE);
- break;
-#endif
case CURL_SSLVERSION_SSLv3:
-#ifdef OPENSSL_NO_SSL3_METHOD
- failf(data, OSSL_PACKAGE " was built without SSLv3 support");
+ failf(data, "No SSLv3 support");
return CURLE_NOT_BUILT_IN;
-#else
-#ifdef USE_OPENSSL_SRP
- if(ssl_authtype == CURL_TLSAUTH_SRP)
- return CURLE_SSL_CONNECT_ERROR;
-#endif
- req_method = SSLv3_client_method();
- use_sni(FALSE);
- break;
-#endif
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
@@ -2609,8 +2669,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#ifdef SSL_CTRL_SET_MSG_CALLBACK
if(data->set.fdebug && data->set.verbose) {
/* the SSL trace callback is only used for verbose logging */
- SSL_CTX_set_msg_callback(backend->ctx, ssl_tls_trace);
+ SSL_CTX_set_msg_callback(backend->ctx, ossl_trace);
SSL_CTX_set_msg_callback_arg(backend->ctx, conn);
+ set_logger(conn, data);
}
#endif
@@ -2673,41 +2734,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
switch(ssl_version) {
- /* "--sslv2" option means SSLv2 only, disable all others */
case CURL_SSLVERSION_SSLv2:
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */
- SSL_CTX_set_min_proto_version(backend->ctx, SSL2_VERSION);
- SSL_CTX_set_max_proto_version(backend->ctx, SSL2_VERSION);
-#else
- ctx_options |= SSL_OP_NO_SSLv3;
- ctx_options |= SSL_OP_NO_TLSv1;
-# if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-# ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-# endif
-# endif
-#endif
- break;
-
- /* "--sslv3" option means SSLv3 only, disable all others */
case CURL_SSLVERSION_SSLv3:
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */
- SSL_CTX_set_min_proto_version(backend->ctx, SSL3_VERSION);
- SSL_CTX_set_max_proto_version(backend->ctx, SSL3_VERSION);
-#else
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_TLSv1;
-# if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-# ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-# endif
-# endif
-#endif
- break;
+ return CURLE_NOT_BUILT_IN;
/* "--tlsv<x.y>" options mean TLS >= version <x.y> */
case CURL_SSLVERSION_DEFAULT:
@@ -2748,18 +2777,17 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
int cur = 0;
unsigned char protocols[128];
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifdef USE_HTTP2
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_PROXY
&& (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
#endif
) {
- protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN;
+ protocols[cur++] = ALPN_H2_LENGTH;
- memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID,
- NGHTTP2_PROTO_VERSION_ID_LEN);
- cur += NGHTTP2_PROTO_VERSION_ID_LEN;
- infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
+ cur += ALPN_H2_LENGTH;
+ infof(data, "ALPN, offering %s\n", ALPN_H2);
}
#endif
@@ -2771,37 +2799,20 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
/* expects length prefixed preference ordered list of protocols in wire
* format
*/
- SSL_CTX_set_alpn_protos(backend->ctx, protocols, cur);
+ if(SSL_CTX_set_alpn_protos(backend->ctx, protocols, cur)) {
+ failf(data, "Error setting ALPN");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
}
#endif
if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
- BIO *ssl_cert_bio = NULL;
- BIO *ssl_key_bio = NULL;
- if(ssl_cert_blob) {
- /* the typecast of blob->len is fine since it is guaranteed to never be
- larger than CURL_MAX_INPUT_LENGTH */
- ssl_cert_bio = BIO_new_mem_buf(ssl_cert_blob->data,
- (int)ssl_cert_blob->len);
- if(!ssl_cert_bio)
- result = CURLE_OUT_OF_MEMORY;
- }
- if(!result && SSL_SET_OPTION(key_blob)) {
- ssl_key_bio = BIO_new_mem_buf(SSL_SET_OPTION(key_blob)->data,
- (int)SSL_SET_OPTION(key_blob)->len);
- if(!ssl_key_bio)
- result = CURLE_OUT_OF_MEMORY;
- }
if(!result &&
!cert_stuff(data, backend->ctx,
- ssl_cert, ssl_cert_bio, ssl_cert_type,
- SSL_SET_OPTION(key), ssl_key_bio,
+ ssl_cert, ssl_cert_blob, ssl_cert_type,
+ SSL_SET_OPTION(key), SSL_SET_OPTION(key_blob),
SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd)))
result = CURLE_SSL_CERTPROBLEM;
- if(ssl_cert_bio)
- BIO_free(ssl_cert_bio);
- if(ssl_key_bio)
- BIO_free(ssl_key_bio);
if(result)
/* failf() is already done in cert_stuff() */
return result;
@@ -2882,8 +2893,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
(SSL_SET_OPTION(native_ca_store))) {
X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
- HCERTSTORE hStore = CertOpenSystemStore((HCRYPTPROV_LEGACY)NULL,
- TEXT("ROOT"));
+ HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
if(hStore) {
PCCERT_CONTEXT pContext = NULL;
@@ -3020,6 +3030,19 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
}
#endif
+ if(ca_info_blob) {
+ result = load_cacert_from_memory(backend->ctx, ca_info_blob);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY ||
+ (verifypeer && !imported_native_ca)) {
+ failf(data, "error importing CA certificate blob");
+ return result;
+ }
+ /* Only warning if no certificate verification is required. */
+ infof(data, "error importing CA certificate blob, continuing anyway\n");
+ }
+ }
+
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
/* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
{
@@ -3076,7 +3099,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
#ifdef CURL_CA_FALLBACK
- if(verifypeer && !ssl_cafile && !ssl_capath && !imported_native_ca) {
+ if(verifypeer &&
+ !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
/* 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(backend->ctx);
@@ -3206,36 +3230,23 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
}
#endif
- /* Check if there's a cached ID we can/should use here! */
- if(SSL_SET_OPTION(primary.sessionid)) {
- void *ssl_sessionid = NULL;
- int data_idx = ossl_get_ssl_data_index();
- int connectdata_idx = ossl_get_ssl_conn_index();
- int sockindex_idx = ossl_get_ssl_sockindex_index();
+ ossl_associate_connection(data, conn, sockindex);
- if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0) {
- /* Store the data needed for the "new session" callback.
- * The sockindex is stored as a pointer to an array element. */
- SSL_set_ex_data(backend->handle, data_idx, data);
- SSL_set_ex_data(backend->handle, connectdata_idx, conn);
- SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex);
- }
-
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
- /* we got a session id, use it! */
- if(!SSL_set_session(backend->handle, ssl_sessionid)) {
- Curl_ssl_sessionid_unlock(data);
- failf(data, "SSL: SSL_set_session failed: %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)));
- return CURLE_SSL_CONNECT_ERROR;
- }
- /* Informational message */
- infof(data, "SSL re-using session ID\n");
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE,
+ &ssl_sessionid, NULL, sockindex)) {
+ /* we got a session id, use it! */
+ if(!SSL_set_session(backend->handle, ssl_sessionid)) {
+ Curl_ssl_sessionid_unlock(data);
+ failf(data, "SSL: SSL_set_session failed: %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ return CURLE_SSL_CONNECT_ERROR;
}
- Curl_ssl_sessionid_unlock(data);
+ /* Informational message */
+ infof(data, "SSL re-using session ID\n");
}
+ Curl_ssl_sessionid_unlock(data);
#ifndef CURL_DISABLE_PROXY
if(conn->proxy_ssl[sockindex].use) {
@@ -3340,6 +3351,19 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
error_buffer */
strcpy(error_buffer, "SSL certificate verification failed");
}
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
+ !defined(LIBRESSL_VERSION_NUMBER) && \
+ !defined(OPENSSL_IS_BORINGSSL))
+ /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on
+ OpenSSL version above v1.1.1, not Libre SSL nor BoringSSL */
+ else if((lib == ERR_LIB_SSL) &&
+ (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) {
+ /* If client certificate is required, communicate the
+ error to client */
+ result = CURLE_SSL_CLIENTCERT;
+ ossl_strerror(errdetail, error_buffer, sizeof(error_buffer));
+ }
+#endif
else {
result = CURLE_SSL_CONNECT_ERROR;
ossl_strerror(errdetail, error_buffer, sizeof(error_buffer));
@@ -3353,11 +3377,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
*/
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
const char * const hostname = SSL_HOST_NAME();
-#ifndef CURL_DISABLE_PROXY
- const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
-#else
- const long int port = conn->remote_port;
-#endif
+ const long int port = SSL_HOST_PORT();
char extramsg[80]="";
int sockerr = SOCKERRNO;
if(sockerr && detail == SSL_ERROR_SYSCALL)
@@ -3380,7 +3400,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
/* Informational message */
infof(data, "SSL connection using %s / %s\n",
- get_ssl_version_txt(backend->handle),
+ SSL_get_version(backend->handle),
SSL_get_cipher(backend->handle));
#ifdef HAS_ALPN
@@ -3391,12 +3411,12 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
const unsigned char *neg_protocol;
unsigned int len;
SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len);
- if(len != 0) {
+ if(len) {
infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
-#ifdef USE_NGHTTP2
- if(len == NGHTTP2_PROTO_VERSION_ID_LEN &&
- !memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len)) {
+#ifdef USE_HTTP2
+ if(len == ALPN_H2_LENGTH &&
+ !memcmp(ALPN_H2, neg_protocol, len)) {
conn->negnpn = CURL_HTTP_VERSION_2;
}
else
@@ -3515,6 +3535,12 @@ typedef size_t numcert_t;
typedef int numcert_t;
#endif
+#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+#define OSSL3_CONST const
+#else
+#define OSSL3_CONST
+#endif
+
static CURLcode get_cert_chain(struct Curl_easy *data,
struct ssl_connect_data *connssl)
{
@@ -3622,7 +3648,7 @@ static CURLcode get_cert_chain(struct Curl_easy *data,
switch(pktype) {
case EVP_PKEY_RSA:
{
- RSA *rsa;
+ OSSL3_CONST RSA *rsa;
#ifdef HAVE_OPAQUE_EVP_PKEY
rsa = EVP_PKEY_get0_RSA(pubkey);
#else
@@ -3652,7 +3678,7 @@ static CURLcode get_cert_chain(struct Curl_easy *data,
case EVP_PKEY_DSA:
{
#ifndef OPENSSL_NO_DSA
- DSA *dsa;
+ OSSL3_CONST DSA *dsa;
#ifdef HAVE_OPAQUE_EVP_PKEY
dsa = EVP_PKEY_get0_DSA(pubkey);
#else
@@ -3684,7 +3710,7 @@ static CURLcode get_cert_chain(struct Curl_easy *data,
}
case EVP_PKEY_DH:
{
- DH *dh;
+ OSSL3_CONST DH *dh;
#ifdef HAVE_OPAQUE_EVP_PKEY
dh = EVP_PKEY_get0_DH(pubkey);
#else
@@ -3877,7 +3903,7 @@ static CURLcode servercert(struct Curl_easy *data,
(int)SSL_SET_OPTION(issuercert_blob)->len);
else {
fp = BIO_new(BIO_s_file());
- if(fp == NULL) {
+ if(!fp) {
failf(data,
"BIO_new return NULL, " OSSL_PACKAGE
" error %s",
@@ -3964,8 +3990,7 @@ static CURLcode servercert(struct Curl_easy *data,
/* when not strict, we don't bother about the verify cert problems */
result = CURLE_OK;
- ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ ptr = SSL_PINNED_PUB_KEY();
if(!result && ptr) {
result = pkp_pin_peer_pubkey(data, backend->server_cert, ptr);
if(result)
@@ -4176,6 +4201,7 @@ static ssize_t ossl_send(struct Curl_easy *data,
ERR_clear_error();
memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
+ set_logger(conn, data);
rc = SSL_write(backend->handle, mem, memlen);
if(rc <= 0) {
@@ -4254,6 +4280,7 @@ static ssize_t ossl_recv(struct Curl_easy *data, /* transfer */
ERR_clear_error();
buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
+ set_logger(conn, data);
nread = (ssize_t)SSL_read(backend->handle, buf, buffsize);
if(nread <= 0) {
/* failed SSL_read */
@@ -4453,10 +4480,95 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl,
(void *)backend->ctx : (void *)backend->handle;
}
+static void ossl_associate_connection(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_backend_data *backend = connssl->backend;
+
+ /* If we don't have SSL context, do nothing. */
+ if(!backend->handle)
+ return;
+
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ int data_idx = ossl_get_ssl_data_index();
+ int connectdata_idx = ossl_get_ssl_conn_index();
+ int sockindex_idx = ossl_get_ssl_sockindex_index();
+ int proxy_idx = ossl_get_proxy_index();
+
+ if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 &&
+ proxy_idx >= 0) {
+ /* Store the data needed for the "new session" callback.
+ * The sockindex is stored as a pointer to an array element. */
+ SSL_set_ex_data(backend->handle, data_idx, data);
+ SSL_set_ex_data(backend->handle, connectdata_idx, conn);
+ SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex);
+#ifndef CURL_DISABLE_PROXY
+ SSL_set_ex_data(backend->handle, proxy_idx, SSL_IS_PROXY() ? (void *) 1:
+ NULL);
+#else
+ SSL_set_ex_data(backend->handle, proxy_idx, NULL);
+#endif
+ }
+ }
+}
+
+/*
+ * Starting with TLS 1.3, the ossl_new_session_cb callback gets called after
+ * the handshake. If the transfer that sets up the callback gets killed before
+ * this callback arrives, we must make sure to properly clear the data to
+ * avoid UAF problems. A future optimization could be to instead store another
+ * transfer that might still be using the same connection.
+ */
+
+static void ossl_disassociate_connection(struct Curl_easy *data,
+ int sockindex)
+{
+ struct connectdata *conn = data->conn;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_backend_data *backend = connssl->backend;
+
+ /* If we don't have SSL context, do nothing. */
+ if(!backend->handle)
+ return;
+
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ bool isproxy = FALSE;
+ bool incache;
+ void *old_ssl_sessionid = NULL;
+ int data_idx = ossl_get_ssl_data_index();
+ int connectdata_idx = ossl_get_ssl_conn_index();
+ int sockindex_idx = ossl_get_ssl_sockindex_index();
+ int proxy_idx = ossl_get_proxy_index();
+
+ if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 &&
+ proxy_idx >= 0) {
+ /* Invalidate the session cache entry, if any */
+ isproxy = SSL_get_ex_data(backend->handle, proxy_idx) ? TRUE : FALSE;
+
+ /* Disable references to data in "new session" callback to avoid
+ * accessing a stale pointer. */
+ SSL_set_ex_data(backend->handle, data_idx, NULL);
+ SSL_set_ex_data(backend->handle, connectdata_idx, NULL);
+ SSL_set_ex_data(backend->handle, sockindex_idx, NULL);
+ SSL_set_ex_data(backend->handle, proxy_idx, NULL);
+ }
+
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn, isproxy,
+ &old_ssl_sessionid, NULL, sockindex));
+ if(incache)
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
+ Curl_ssl_sessionid_unlock(data);
+ }
+}
+
const struct Curl_ssl Curl_ssl_openssl = {
{ CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
SSLSUPP_CA_PATH |
+ SSLSUPP_CAINFO_BLOB |
SSLSUPP_CERTINFO |
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_SSL_CTX |
@@ -4477,6 +4589,7 @@ const struct Curl_ssl Curl_ssl_openssl = {
ossl_cert_status_request, /* cert_status_request */
ossl_connect, /* connect */
ossl_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
ossl_get_internals, /* get_internals */
ossl_close, /* close_one */
ossl_close_all, /* close_all */
@@ -4486,10 +4599,12 @@ const struct Curl_ssl Curl_ssl_openssl = {
ossl_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
- ossl_sha256sum /* sha256sum */
+ ossl_sha256sum, /* sha256sum */
#else
- NULL /* sha256sum */
+ NULL, /* sha256sum */
#endif
+ ossl_associate_connection, /* associate_connection */
+ ossl_disassociate_connection /* disassociate_connection */
};
#endif /* USE_OPENSSL */
diff --git a/Utilities/cmcurl/lib/vtls/rustls.c b/Utilities/cmcurl/lib/vtls/rustls.c
new file mode 100644
index 000000000..d5247f936
--- /dev/null
+++ b/Utilities/cmcurl/lib/vtls/rustls.c
@@ -0,0 +1,583 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020 - 2021, Jacob Hoffman-Andrews,
+ * <github@hoffman-andrews.com>
+ *
+ * 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"
+
+#ifdef USE_RUSTLS
+
+#include "curl_printf.h"
+
+#include <errno.h>
+#include <crustls.h>
+
+#include "inet_pton.h"
+#include "urldata.h"
+#include "sendf.h"
+#include "vtls.h"
+#include "select.h"
+
+#include "multiif.h"
+
+struct ssl_backend_data
+{
+ const struct rustls_client_config *config;
+ struct rustls_connection *conn;
+ bool data_pending;
+};
+
+/* For a given rustls_result error code, return the best-matching CURLcode. */
+static CURLcode map_error(rustls_result r)
+{
+ if(rustls_result_is_cert_error(r)) {
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ switch(r) {
+ case RUSTLS_RESULT_OK:
+ return CURLE_OK;
+ case RUSTLS_RESULT_NULL_PARAMETER:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ default:
+ return CURLE_READ_ERROR;
+ }
+}
+
+static bool
+cr_data_pending(const struct connectdata *conn, int sockindex)
+{
+ const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_backend_data *backend = connssl->backend;
+ return backend->data_pending;
+}
+
+static CURLcode
+cr_connect(struct Curl_easy *data UNUSED_PARAM,
+ struct connectdata *conn UNUSED_PARAM,
+ int sockindex UNUSED_PARAM)
+{
+ infof(data, "rustls_connect: unimplemented\n");
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+static int
+read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
+{
+ ssize_t n = sread(*(int *)userdata, buf, len);
+ if(n < 0) {
+ return SOCKERRNO;
+ }
+ *out_n = n;
+ return 0;
+}
+
+static int
+write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
+{
+ ssize_t n = swrite(*(int *)userdata, buf, len);
+ if(n < 0) {
+ return SOCKERRNO;
+ }
+ *out_n = n;
+ return 0;
+}
+
+/*
+ * On each run:
+ * - Read a chunk of bytes from the socket into rustls' TLS input buffer.
+ * - Tell rustls to process any new packets.
+ * - Read out as many plaintext bytes from rustls as possible, until hitting
+ * error, EOF, or EAGAIN/EWOULDBLOCK, or plainbuf/plainlen is filled up.
+ *
+ * It's okay to call this function with plainbuf == NULL and plainlen == 0.
+ * In that case, it will copy bytes from the socket into rustls' TLS input
+ * buffer, and process packets, but won't consume bytes from rustls' plaintext
+ * output buffer.
+ */
+static ssize_t
+cr_recv(struct Curl_easy *data, int sockindex,
+ char *plainbuf, size_t plainlen, CURLcode *err)
+{
+ struct connectdata *conn = data->conn;
+ struct ssl_connect_data *const connssl = &conn->ssl[sockindex];
+ struct ssl_backend_data *const backend = connssl->backend;
+ struct rustls_connection *const rconn = backend->conn;
+ size_t n = 0;
+ size_t tls_bytes_read = 0;
+ size_t plain_bytes_copied = 0;
+ rustls_result rresult = 0;
+ char errorbuf[255];
+ rustls_io_result io_error;
+
+ io_error = rustls_connection_read_tls(rconn, read_cb,
+ &conn->sock[sockindex], &tls_bytes_read);
+ if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
+ infof(data, "sread: EAGAIN or EWOULDBLOCK\n");
+ }
+ else if(io_error) {
+ failf(data, "reading from socket: %s", strerror(io_error));
+ *err = CURLE_READ_ERROR;
+ return -1;
+ }
+ else if(tls_bytes_read == 0) {
+ failf(data, "connection closed without TLS close_notify alert");
+ *err = CURLE_READ_ERROR;
+ return -1;
+ }
+
+ infof(data, "cr_recv read %ld bytes from the network\n", tls_bytes_read);
+
+ rresult = rustls_connection_process_new_packets(rconn);
+ if(rresult != RUSTLS_RESULT_OK) {
+ rustls_error(rresult, errorbuf, sizeof(errorbuf), &n);
+ failf(data, "%.*s", n, errorbuf);
+ *err = map_error(rresult);
+ return -1;
+ }
+
+ backend->data_pending = TRUE;
+
+ while(plain_bytes_copied < plainlen) {
+ rresult = rustls_connection_read(rconn,
+ (uint8_t *)plainbuf + plain_bytes_copied,
+ plainlen - plain_bytes_copied,
+ &n);
+ if(rresult == RUSTLS_RESULT_ALERT_CLOSE_NOTIFY) {
+ *err = CURLE_OK;
+ return 0;
+ }
+ else if(rresult != RUSTLS_RESULT_OK) {
+ failf(data, "error in rustls_connection_read");
+ *err = CURLE_READ_ERROR;
+ return -1;
+ }
+ else if(n == 0) {
+ /* rustls returns 0 from connection_read to mean "all currently
+ available data has been read." If we bring in more ciphertext with
+ read_tls, more plaintext will become available. So don't tell curl
+ this is an EOF. Instead, say "come back later." */
+ infof(data, "cr_recv got 0 bytes of plaintext\n");
+ backend->data_pending = FALSE;
+ break;
+ }
+ else {
+ infof(data, "cr_recv copied out %ld bytes of plaintext\n", n);
+ plain_bytes_copied += n;
+ }
+ }
+
+ /* If we wrote out 0 plaintext bytes, it might just mean we haven't yet
+ read a full TLS record. Return CURLE_AGAIN so curl doesn't treat this
+ as EOF. */
+ if(plain_bytes_copied == 0) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+
+ return plain_bytes_copied;
+}
+
+/*
+ * On each call:
+ * - Copy `plainlen` bytes into rustls' plaintext input buffer (if > 0).
+ * - Fully drain rustls' plaintext output buffer into the socket until
+ * we get either an error or EAGAIN/EWOULDBLOCK.
+ *
+ * It's okay to call this function with plainbuf == NULL and plainlen == 0.
+ * In that case, it won't read anything into rustls' plaintext input buffer.
+ * It will only drain rustls' plaintext output buffer into the socket.
+ */
+static ssize_t
+cr_send(struct Curl_easy *data, int sockindex,
+ const void *plainbuf, size_t plainlen, CURLcode *err)
+{
+ struct connectdata *conn = data->conn;
+ struct ssl_connect_data *const connssl = &conn->ssl[sockindex];
+ struct ssl_backend_data *const backend = connssl->backend;
+ struct rustls_connection *const rconn = backend->conn;
+ size_t plainwritten = 0;
+ size_t tlswritten = 0;
+ size_t tlswritten_total = 0;
+ rustls_result rresult;
+ rustls_io_result io_error;
+
+ infof(data, "cr_send %ld bytes of plaintext\n", plainlen);
+
+ if(plainlen > 0) {
+ rresult = rustls_connection_write(rconn, plainbuf, plainlen,
+ &plainwritten);
+ if(rresult != RUSTLS_RESULT_OK) {
+ failf(data, "error in rustls_connection_write");
+ *err = CURLE_WRITE_ERROR;
+ return -1;
+ }
+ else if(plainwritten == 0) {
+ failf(data, "EOF in rustls_connection_write");
+ *err = CURLE_WRITE_ERROR;
+ return -1;
+ }
+ }
+
+ while(rustls_connection_wants_write(rconn)) {
+ io_error = rustls_connection_write_tls(rconn, write_cb,
+ &conn->sock[sockindex], &tlswritten);
+ if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
+ infof(data, "swrite: EAGAIN after %ld bytes\n", tlswritten_total);
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+ else if(io_error) {
+ failf(data, "writing to socket: %s", strerror(io_error));
+ *err = CURLE_WRITE_ERROR;
+ return -1;
+ }
+ if(tlswritten == 0) {
+ failf(data, "EOF in swrite");
+ *err = CURLE_WRITE_ERROR;
+ return -1;
+ }
+ infof(data, "cr_send wrote %ld bytes to network\n", tlswritten);
+ tlswritten_total += tlswritten;
+ }
+
+ return plainwritten;
+}
+
+/* A server certificate verify callback for rustls that always returns
+ RUSTLS_RESULT_OK, or in other words disable certificate verification. */
+static enum rustls_result
+cr_verify_none(void *userdata UNUSED_PARAM,
+ const rustls_verify_server_cert_params *params UNUSED_PARAM)
+{
+ return RUSTLS_RESULT_OK;
+}
+
+static bool
+cr_hostname_is_ip(const char *hostname)
+{
+ struct in_addr in;
+#ifdef ENABLE_IPV6
+ struct in6_addr in6;
+ if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) {
+ return true;
+ }
+#endif /* ENABLE_IPV6 */
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
+ return true;
+ }
+ return false;
+}
+
+static CURLcode
+cr_init_backend(struct Curl_easy *data, struct connectdata *conn,
+ struct ssl_backend_data *const backend)
+{
+ struct rustls_connection *rconn = backend->conn;
+ struct rustls_client_config_builder *config_builder = NULL;
+ const char *const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+ const char *hostname = conn->host.name;
+ char errorbuf[256];
+ size_t errorlen;
+ int result;
+ rustls_slice_bytes alpn[2] = {
+ { (const uint8_t *)ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH },
+ { (const uint8_t *)ALPN_H2, ALPN_H2_LENGTH },
+ };
+
+ config_builder = rustls_client_config_builder_new();
+#ifdef USE_HTTP2
+ infof(data, "offering ALPN for HTTP/1.1 and HTTP/2\n");
+ rustls_client_config_builder_set_protocols(config_builder, alpn, 2);
+#else
+ infof(data, "offering ALPN for HTTP/1.1 only\n");
+ rustls_client_config_builder_set_protocols(config_builder, alpn, 1);
+#endif
+ if(!verifypeer) {
+ rustls_client_config_builder_dangerous_set_certificate_verifier(
+ config_builder, cr_verify_none);
+ /* rustls doesn't support IP addresses (as of 0.19.0), and will reject
+ * connections created with an IP address, even when certificate
+ * verification is turned off. Set a placeholder hostname and disable
+ * SNI. */
+ if(cr_hostname_is_ip(hostname)) {
+ rustls_client_config_builder_set_enable_sni(config_builder, false);
+ hostname = "example.invalid";
+ }
+ }
+ else if(ssl_cafile) {
+ result = rustls_client_config_builder_load_roots_from_file(
+ config_builder, ssl_cafile);
+ if(result != RUSTLS_RESULT_OK) {
+ failf(data, "failed to load trusted certificates");
+ rustls_client_config_free(
+ rustls_client_config_builder_build(config_builder));
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else {
+ result = rustls_client_config_builder_load_native_roots(config_builder);
+ if(result != RUSTLS_RESULT_OK) {
+ failf(data, "failed to load trusted certificates");
+ rustls_client_config_free(
+ rustls_client_config_builder_build(config_builder));
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+
+ backend->config = rustls_client_config_builder_build(config_builder);
+ DEBUGASSERT(rconn == NULL);
+ result = rustls_client_connection_new(backend->config, hostname, &rconn);
+ if(result != RUSTLS_RESULT_OK) {
+ rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen);
+ failf(data, "rustls_client_connection_new: %.*s", errorlen, errorbuf);
+ return CURLE_COULDNT_CONNECT;
+ }
+ rustls_connection_set_userdata(rconn, backend);
+ backend->conn = rconn;
+ return CURLE_OK;
+}
+
+static void
+cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn,
+ const struct rustls_connection *rconn)
+{
+ const uint8_t *protocol = NULL;
+ size_t len = 0;
+
+ rustls_connection_get_alpn_protocol(rconn, &protocol, &len);
+ if(NULL == protocol) {
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ return;
+ }
+
+#ifdef USE_HTTP2
+ if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) {
+ infof(data, "ALPN, negotiated h2\n");
+ conn->negnpn = CURL_HTTP_VERSION_2;
+ }
+ else
+#endif
+ if(len == ALPN_HTTP_1_1_LENGTH &&
+ 0 == memcmp(ALPN_HTTP_1_1, protocol, len)) {
+ infof(data, "ALPN, negotiated http/1.1\n");
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
+ else {
+ infof(data, "ALPN, negotiated an unrecognized protocol\n");
+ }
+
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+}
+
+static CURLcode
+cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, bool *done)
+{
+ struct ssl_connect_data *const connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_backend_data *const backend = connssl->backend;
+ struct rustls_connection *rconn = NULL;
+ CURLcode tmperr = CURLE_OK;
+ int result;
+ int what;
+ bool wants_read;
+ bool wants_write;
+ curl_socket_t writefd;
+ curl_socket_t readfd;
+
+ if(ssl_connection_none == connssl->state) {
+ result = cr_init_backend(data, conn, connssl->backend);
+ if(result != CURLE_OK) {
+ return result;
+ }
+ connssl->state = ssl_connection_negotiating;
+ }
+
+ rconn = backend->conn;
+
+ /* Read/write data until the handshake is done or the socket would block. */
+ for(;;) {
+ /*
+ * Connection has been established according to rustls. Set send/recv
+ * handlers, and update the state machine.
+ * This check has to come last because is_handshaking starts out false,
+ * then becomes true when we first write data, then becomes false again
+ * once the handshake is done.
+ */
+ if(!rustls_connection_is_handshaking(rconn)) {
+ infof(data, "Done handshaking\n");
+ /* Done with the handshake. Set up callbacks to send/receive data. */
+ connssl->state = ssl_connection_complete;
+
+ cr_set_negotiated_alpn(data, conn, rconn);
+
+ conn->recv[sockindex] = cr_recv;
+ conn->send[sockindex] = cr_send;
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ wants_read = rustls_connection_wants_read(rconn);
+ wants_write = rustls_connection_wants_write(rconn);
+ DEBUGASSERT(wants_read || wants_write);
+ writefd = wants_write?sockfd:CURL_SOCKET_BAD;
+ readfd = wants_read?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 0);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ if(0 == what) {
+ infof(data, "Curl_socket_check: %s would block\n",
+ wants_read&&wants_write ?
+ "writing and reading" :
+ wants_write ?
+ "writing" :
+ "reading");
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ /* socket is readable or writable */
+
+ if(wants_write) {
+ infof(data, "rustls_connection wants us to write_tls.\n");
+ cr_send(data, sockindex, NULL, 0, &tmperr);
+ if(tmperr == CURLE_AGAIN) {
+ infof(data, "writing would block\n");
+ /* fall through */
+ }
+ else if(tmperr != CURLE_OK) {
+ return tmperr;
+ }
+ }
+
+ if(wants_read) {
+ infof(data, "rustls_connection wants us to read_tls.\n");
+
+ cr_recv(data, sockindex, NULL, 0, &tmperr);
+ if(tmperr == CURLE_AGAIN) {
+ infof(data, "reading would block\n");
+ /* fall through */
+ }
+ else if(tmperr != CURLE_OK) {
+ if(tmperr == CURLE_READ_ERROR) {
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ return tmperr;
+ }
+ }
+ }
+ }
+
+ /* We should never fall through the loop. We should return either because
+ the handshake is done or because we can't read/write without blocking. */
+ DEBUGASSERT(false);
+}
+
+/* returns a bitmap of flags for this connection's first socket indicating
+ whether we want to read or write */
+static int
+cr_getsock(struct connectdata *conn, curl_socket_t *socks)
+{
+ struct ssl_connect_data *const connssl = &conn->ssl[FIRSTSOCKET];
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+ struct ssl_backend_data *const backend = connssl->backend;
+ struct rustls_connection *rconn = backend->conn;
+
+ if(rustls_connection_wants_write(rconn)) {
+ socks[0] = sockfd;
+ return GETSOCK_WRITESOCK(0);
+ }
+ if(rustls_connection_wants_read(rconn)) {
+ socks[0] = sockfd;
+ return GETSOCK_READSOCK(0);
+ }
+
+ return GETSOCK_BLANK;
+}
+
+static void *
+cr_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ struct ssl_backend_data *backend = connssl->backend;
+ return &backend->conn;
+}
+
+static void
+cr_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_backend_data *backend = connssl->backend;
+ CURLcode tmperr = CURLE_OK;
+ ssize_t n = 0;
+
+ if(backend->conn) {
+ rustls_connection_send_close_notify(backend->conn);
+ n = cr_send(data, sockindex, NULL, 0, &tmperr);
+ if(n < 0) {
+ failf(data, "error sending close notify: %d", tmperr);
+ }
+
+ rustls_connection_free(backend->conn);
+ backend->conn = NULL;
+ }
+ if(backend->config) {
+ rustls_client_config_free(backend->config);
+ backend->config = NULL;
+ }
+}
+
+const struct Curl_ssl Curl_ssl_rustls = {
+ { CURLSSLBACKEND_RUSTLS, "rustls" },
+ SSLSUPP_TLS13_CIPHERSUITES, /* supports */
+ sizeof(struct ssl_backend_data),
+
+ Curl_none_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ rustls_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_none_shutdown, /* shutdown */
+ cr_data_pending, /* data_pending */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ cr_connect, /* connect */
+ cr_connect_nonblocking, /* connect_nonblocking */
+ cr_getsock, /* cr_getsock */
+ cr_get_internals, /* get_internals */
+ cr_close, /* close_one */
+ Curl_none_close_all, /* close_all */
+ Curl_none_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
+};
+
+#endif /* USE_RUSTLS */
diff --git a/Utilities/cmcurl/lib/vtls/rustls.h b/Utilities/cmcurl/lib/vtls/rustls.h
new file mode 100644
index 000000000..056211dd8
--- /dev/null
+++ b/Utilities/cmcurl/lib/vtls/rustls.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020 - 2021, Jacob Hoffman-Andrews,
+ * <github@hoffman-andrews.com>
+ *
+ * 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.
+ *
+ ***************************************************************************/
+#ifndef HEADER_CURL_RUSTLS_H
+#define HEADER_CURL_RUSTLS_H
+
+#include "curl_setup.h"
+
+#ifdef USE_RUSTLS
+
+extern const struct Curl_ssl Curl_ssl_rustls;
+
+#endif /* USE_RUSTLS */
+#endif /* HEADER_CURL_RUSTLS_H */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 0668f98f2..3286a9e9f 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -117,6 +117,10 @@
#define SP_PROT_TLS1_2_CLIENT 0x00000800
#endif
+#ifndef SCH_USE_STRONG_CRYPTO
+#define SCH_USE_STRONG_CRYPTO 0x00400000
+#endif
+
#ifndef SECBUFFER_ALERT
#define SECBUFFER_ALERT 17
#endif
@@ -324,17 +328,22 @@ get_alg_id_by_name(char *name)
}
static CURLcode
-set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
+set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers,
+ ALG_ID *algIds)
{
char *startCur = ciphers;
int algCount = 0;
- static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/
- while(startCur && (0 != *startCur) && (algCount < 45)) {
+ while(startCur && (0 != *startCur) && (algCount < NUMOF_CIPHERS)) {
long alg = strtol(startCur, 0, 0);
if(!alg)
alg = get_alg_id_by_name(startCur);
if(alg)
algIds[algCount++] = alg;
+ else if(!strncmp(startCur, "USE_STRONG_CRYPTO",
+ sizeof("USE_STRONG_CRYPTO") - 1) ||
+ !strncmp(startCur, "SCH_USE_STRONG_CRYPTO",
+ sizeof("SCH_USE_STRONG_CRYPTO") - 1))
+ schannel_cred->dwFlags |= SCH_USE_STRONG_CRYPTO;
else
return CURLE_SSL_CIPHER;
startCur = strchr(startCur, ':');
@@ -358,7 +367,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
size_t store_name_len;
sep = _tcschr(path, TEXT('\\'));
- if(sep == NULL)
+ if(!sep)
return CURLE_SSL_CERTPROBLEM;
store_name_len = sep - path;
@@ -388,7 +397,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
store_path_start = sep + 1;
sep = _tcschr(store_path_start, TEXT('\\'));
- if(sep == NULL)
+ if(!sep)
return CURLE_SSL_CERTPROBLEM;
*thumbprint = sep + 1;
@@ -398,7 +407,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
*sep = TEXT('\0');
*store_path = _tcsdup(store_path_start);
*sep = TEXT('\\');
- if(*store_path == NULL)
+ if(!*store_path)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -428,12 +437,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#endif
TCHAR *host_name;
CURLcode result;
-#ifndef CURL_DISABLE_PROXY
- char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- char * const hostname = conn->host.name;
-#endif
+ char * const hostname = SSL_HOST_NAME();
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
@@ -469,7 +473,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#endif
#else
#ifdef HAS_MANUAL_VERIFY_API
- if(SSL_CONN_CONFIG(CAfile)) {
+ if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) {
if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) {
BACKEND->use_manual_cred_validation = true;
@@ -483,7 +487,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
else
BACKEND->use_manual_cred_validation = false;
#else
- if(SSL_CONN_CONFIG(CAfile)) {
+ if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) {
failf(data, "schannel: CA cert support not built in");
return CURLE_NOT_BUILT_IN;
}
@@ -496,6 +500,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
if(SSL_SET_OPTION(primary.sessionid)) {
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
(void **)&old_cred, NULL, sockindex)) {
BACKEND->cred = old_cred;
DEBUGF(infof(data, "schannel: re-using existing credential handle\n"));
@@ -522,14 +527,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#endif
schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
- if(data->set.ssl.no_revoke) {
+ if(SSL_SET_OPTION(no_revoke)) {
schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE;
DEBUGF(infof(data, "schannel: disabled server certificate revocation "
"checks\n"));
}
- else if(data->set.ssl.revoke_best_effort) {
+ else if(SSL_SET_OPTION(revoke_best_effort)) {
schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN;
@@ -557,6 +562,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
"names in server certificates.\n"));
}
+ if(!SSL_SET_OPTION(auto_client_cert)) {
+ schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS;
+ schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
+ infof(data, "schannel: disabled automatic use of client certificate\n");
+ }
+ else
+ infof(data, "schannel: enabled automatic use of client certificate\n");
+
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
@@ -571,18 +584,17 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
break;
}
case CURL_SSLVERSION_SSLv3:
- schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
- break;
case CURL_SSLVERSION_SSLv2:
- schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
- break;
+ failf(data, "SSL versions not supported");
+ return CURLE_NOT_BUILT_IN;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
}
if(SSL_CONN_CONFIG(cipher_list)) {
- result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list));
+ result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list),
+ BACKEND->algIds);
if(CURLE_OK != result) {
failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
return result;
@@ -699,7 +711,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
}
if(!blob)
free(certdata);
- if(cert_store == NULL) {
+ if(!cert_store) {
DWORD errorcode = GetLastError();
if(errorcode == ERROR_INVALID_PASSWORD)
failf(data, "schannel: Failed to import cert file %s, "
@@ -716,7 +728,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
CERT_FIND_ANY, NULL, NULL);
- if(client_certs[0] == NULL) {
+ if(!client_certs[0]) {
failf(data, "schannel: Failed to get certificate from file %s"
", last error is 0x%x",
cert_showfilename_error, GetLastError());
@@ -860,11 +872,12 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
list_start_index = cur;
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
- memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN);
- cur += NGHTTP2_PROTO_ALPN_LEN;
- infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+#ifdef USE_HTTP2
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
+ alpn_buffer[cur++] = ALPN_H2_LENGTH;
+ memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH);
+ cur += ALPN_H2_LENGTH;
+ infof(data, "schannel: ALPN, offering %s\n", ALPN_H2);
}
#endif
@@ -892,11 +905,15 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
- /* setup request flags */
+ /* security request flags */
BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_STREAM;
+ if(!SSL_SET_OPTION(auto_client_cert)) {
+ BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
+ }
+
/* allocate memory for the security context handle */
BACKEND->ctxt = (struct Curl_schannel_ctxt *)
calloc(1, sizeof(struct Curl_schannel_ctxt));
@@ -996,12 +1013,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
bool doread;
-#ifndef CURL_DISABLE_PROXY
- char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- char * const hostname = conn->host.name;
-#endif
+ char * const hostname = SSL_HOST_NAME();
const char *pubkey_ptr;
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
@@ -1014,23 +1026,23 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
/* buffer to store previously received and decrypted data */
- if(BACKEND->decdata_buffer == NULL) {
+ if(!BACKEND->decdata_buffer) {
BACKEND->decdata_offset = 0;
BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
BACKEND->decdata_buffer = malloc(BACKEND->decdata_length);
- if(BACKEND->decdata_buffer == NULL) {
+ if(!BACKEND->decdata_buffer) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
}
/* buffer to store previously received and encrypted data */
- if(BACKEND->encdata_buffer == NULL) {
+ if(!BACKEND->encdata_buffer) {
BACKEND->encdata_is_incomplete = false;
BACKEND->encdata_offset = 0;
BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
BACKEND->encdata_buffer = malloc(BACKEND->encdata_length);
- if(BACKEND->encdata_buffer == NULL) {
+ if(!BACKEND->encdata_buffer) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
@@ -1045,7 +1057,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length);
- if(reallocated_buffer == NULL) {
+ if(!reallocated_buffer) {
failf(data, "schannel: unable to re-allocate memory");
return CURLE_OUT_OF_MEMORY;
}
@@ -1100,7 +1112,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, outbuf, 3);
- if(inbuf[0].pvBuffer == NULL) {
+ if(!inbuf[0].pvBuffer) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
@@ -1250,9 +1262,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n"));
}
- pubkey_ptr = SSL_IS_PROXY() ?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ pubkey_ptr = SSL_PINNED_PUB_KEY();
if(pubkey_ptr) {
result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr);
if(result) {
@@ -1337,9 +1347,9 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
+ bool isproxy = SSL_IS_PROXY();
#ifdef DEBUGBUILD
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
+ const char * const hostname = SSL_HOST_NAME();
#endif
#ifdef HAS_ALPN
SecPkgContext_ApplicationProtocol alpn_result;
@@ -1387,10 +1397,9 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
infof(data, "schannel: ALPN, server accepted to use %.*s\n",
alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
-#ifdef USE_NGHTTP2
- if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN &&
- !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId,
- NGHTTP2_PROTO_VERSION_ID_LEN)) {
+#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;
}
else
@@ -1414,8 +1423,8 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
struct Curl_schannel_cred *old_cred = NULL;
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn, (void **)&old_cred, NULL,
- sockindex));
+ incache = !(Curl_ssl_getsessionid(data, conn, isproxy, (void **)&old_cred,
+ NULL, sockindex));
if(incache) {
if(old_cred != BACKEND->cred) {
DEBUGF(infof(data,
@@ -1426,7 +1435,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(data, conn, (void *)BACKEND->cred,
+ result = Curl_ssl_addsessionid(data, conn, isproxy, BACKEND->cred,
sizeof(struct Curl_schannel_cred),
sockindex);
if(result) {
@@ -1451,7 +1460,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&ccert_context);
- if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
+ if((sspi_status != SEC_E_OK) || !ccert_context) {
failf(data, "schannel: failed to retrieve remote cert context");
return CURLE_PEER_FAILED_VERIFICATION;
}
@@ -1803,7 +1812,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
}
reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length);
- if(reallocated_buffer == NULL) {
+ if(!reallocated_buffer) {
*err = CURLE_OUT_OF_MEMORY;
failf(data, "schannel: unable to re-allocate memory");
goto cleanup;
@@ -1892,7 +1901,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
}
reallocated_buffer = realloc(BACKEND->decdata_buffer,
reallocated_length);
- if(reallocated_buffer == NULL) {
+ if(!reallocated_buffer) {
*err = CURLE_OUT_OF_MEMORY;
failf(data, "schannel: unable to re-allocate memory");
goto cleanup;
@@ -2126,12 +2135,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
* Shutting Down an Schannel Connection
*/
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-#ifndef CURL_DISABLE_PROXY
- char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- char * const hostname = conn->host.name;
-#endif
+ char * const hostname = SSL_HOST_NAME();
DEBUGASSERT(data);
@@ -2294,7 +2298,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&pCertContextServer);
- if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ if((sspi_status != SEC_E_OK) || !pCertContextServer) {
char buffer[STRERROR_LEN];
failf(data, "schannel: Failed to read remote certificate context: %s",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
@@ -2404,6 +2408,9 @@ const struct Curl_ssl Curl_ssl_schannel = {
{ CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
SSLSUPP_CERTINFO |
+#ifdef HAS_MANUAL_VERIFY_API
+ SSLSUPP_CAINFO_BLOB |
+#endif
SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
@@ -2418,6 +2425,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
Curl_none_cert_status_request, /* cert_status_request */
schannel_connect, /* connect */
schannel_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
schannel_get_internals, /* get_internals */
schannel_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -2426,7 +2434,9 @@ const struct Curl_ssl Curl_ssl_schannel = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- schannel_sha256sum /* sha256sum */
+ schannel_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#endif /* USE_SCHANNEL */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index 2952caa1a..77853aa30 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -71,6 +71,8 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data,
#endif
#endif
+#define NUMOF_CIPHERS 45 /* There are 45 listed in the MS headers */
+
struct Curl_schannel_cred {
CredHandle cred_handle;
TimeStamp time_stamp;
@@ -102,6 +104,7 @@ struct ssl_backend_data {
#ifdef HAS_MANUAL_VERIFY_API
bool use_manual_cred_validation; /* true if manual cred validation is used */
#endif
+ ALG_ID algIds[NUMOF_CIPHERS];
};
#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
index 2ef39cc0f..25d47b808 100644
--- a/Utilities/cmcurl/lib/vtls/schannel_verify.c
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -77,21 +77,156 @@ static int is_cr_or_lf(char c)
return c == '\r' || c == '\n';
}
-static CURLcode add_certs_to_store(HCERTSTORE trust_store,
- const char *ca_file,
- struct Curl_easy *data)
+/* Search the substring needle,needlelen into string haystack,haystacklen
+ * Strings don't need to be terminated by a '\0'.
+ * Similar of OSX/Linux memmem (not available on Visual Studio).
+ * Return position of beginning of first occurence or NULL if not found
+ */
+static const char *c_memmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen)
+{
+ const char *p;
+ char first;
+ const char *str_limit = (const char *)haystack + haystacklen;
+ if(!needlelen || needlelen > haystacklen)
+ return NULL;
+ first = *(const char *)needle;
+ for(p = (const char *)haystack; p <= (str_limit - needlelen); p++)
+ if(((*p) == first) && (memcmp(p, needle, needlelen) == 0))
+ return p;
+
+ return NULL;
+}
+
+static CURLcode add_certs_data_to_store(HCERTSTORE trust_store,
+ const char *ca_buffer,
+ size_t ca_buffer_size,
+ const char *ca_file_text,
+ struct Curl_easy *data)
+{
+ const size_t begin_cert_len = strlen(BEGIN_CERT);
+ const size_t end_cert_len = strlen(END_CERT);
+ CURLcode result = CURLE_OK;
+ int num_certs = 0;
+ bool more_certs = 1;
+ const char *current_ca_file_ptr = ca_buffer;
+ const char *ca_buffer_limit = ca_buffer + ca_buffer_size;
+
+ while(more_certs && (current_ca_file_ptr<ca_buffer_limit)) {
+ const char *begin_cert_ptr = c_memmem(current_ca_file_ptr,
+ ca_buffer_limit-current_ca_file_ptr,
+ BEGIN_CERT,
+ begin_cert_len);
+ if(!begin_cert_ptr || !is_cr_or_lf(begin_cert_ptr[begin_cert_len])) {
+ more_certs = 0;
+ }
+ else {
+ const char *end_cert_ptr = c_memmem(begin_cert_ptr,
+ ca_buffer_limit-begin_cert_ptr,
+ END_CERT,
+ end_cert_len);
+ if(!end_cert_ptr) {
+ failf(data,
+ "schannel: CA file '%s' is not correctly formatted",
+ ca_file_text);
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ CERT_BLOB cert_blob;
+ CERT_CONTEXT *cert_context = NULL;
+ BOOL add_cert_result = FALSE;
+ DWORD actual_content_type = 0;
+ DWORD cert_size = (DWORD)
+ ((end_cert_ptr + end_cert_len) - begin_cert_ptr);
+
+ cert_blob.pbData = (BYTE *)begin_cert_ptr;
+ cert_blob.cbData = cert_size;
+ if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
+ &cert_blob,
+ CERT_QUERY_CONTENT_FLAG_CERT,
+ CERT_QUERY_FORMAT_FLAG_ALL,
+ 0,
+ NULL,
+ &actual_content_type,
+ NULL,
+ NULL,
+ NULL,
+ (const void **)&cert_context)) {
+ char buffer[STRERROR_LEN];
+ failf(data,
+ "schannel: failed to extract certificate from CA file "
+ "'%s': %s",
+ ca_file_text,
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ current_ca_file_ptr = begin_cert_ptr + cert_size;
+
+ /* Sanity check that the cert_context object is the right type */
+ if(CERT_QUERY_CONTENT_CERT != actual_content_type) {
+ failf(data,
+ "schannel: unexpected content type '%d' when extracting "
+ "certificate from CA file '%s'",
+ actual_content_type, ca_file_text);
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ add_cert_result =
+ CertAddCertificateContextToStore(trust_store,
+ cert_context,
+ CERT_STORE_ADD_ALWAYS,
+ NULL);
+ CertFreeCertificateContext(cert_context);
+ if(!add_cert_result) {
+ char buffer[STRERROR_LEN];
+ failf(data,
+ "schannel: failed to add certificate from CA file '%s' "
+ "to certificate store: %s",
+ ca_file_text,
+ Curl_winapi_strerror(GetLastError(), buffer,
+ sizeof(buffer)));
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ num_certs++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ if(!num_certs) {
+ infof(data,
+ "schannel: did not add any certificates from CA file '%s'\n",
+ ca_file_text);
+ }
+ else {
+ infof(data,
+ "schannel: added %d certificate(s) from CA file '%s'\n",
+ num_certs, ca_file_text);
+ }
+ }
+ return result;
+}
+
+static CURLcode add_certs_file_to_store(HCERTSTORE trust_store,
+ const char *ca_file,
+ struct Curl_easy *data)
{
CURLcode result;
HANDLE ca_file_handle = INVALID_HANDLE_VALUE;
LARGE_INTEGER file_size;
char *ca_file_buffer = NULL;
- char *current_ca_file_ptr = NULL;
TCHAR *ca_file_tstr = NULL;
size_t ca_file_bufsize = 0;
DWORD total_bytes_read = 0;
- bool more_certs = 0;
- int num_certs = 0;
- size_t END_CERT_LEN;
ca_file_tstr = curlx_convert_UTF8_to_tchar((char *)ca_file);
if(!ca_file_tstr) {
@@ -181,106 +316,10 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
if(result != CURLE_OK) {
goto cleanup;
}
-
- END_CERT_LEN = strlen(END_CERT);
-
- more_certs = 1;
- current_ca_file_ptr = ca_file_buffer;
- while(more_certs && *current_ca_file_ptr != '\0') {
- char *begin_cert_ptr = strstr(current_ca_file_ptr, BEGIN_CERT);
- if(!begin_cert_ptr || !is_cr_or_lf(begin_cert_ptr[strlen(BEGIN_CERT)])) {
- more_certs = 0;
- }
- else {
- char *end_cert_ptr = strstr(begin_cert_ptr, END_CERT);
- if(!end_cert_ptr) {
- failf(data,
- "schannel: CA file '%s' is not correctly formatted",
- ca_file);
- result = CURLE_SSL_CACERT_BADFILE;
- more_certs = 0;
- }
- else {
- CERT_BLOB cert_blob;
- CERT_CONTEXT *cert_context = NULL;
- BOOL add_cert_result = FALSE;
- DWORD actual_content_type = 0;
- DWORD cert_size = (DWORD)
- ((end_cert_ptr + END_CERT_LEN) - begin_cert_ptr);
-
- cert_blob.pbData = (BYTE *)begin_cert_ptr;
- cert_blob.cbData = cert_size;
- if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
- &cert_blob,
- CERT_QUERY_CONTENT_FLAG_CERT,
- CERT_QUERY_FORMAT_FLAG_ALL,
- 0,
- NULL,
- &actual_content_type,
- NULL,
- NULL,
- NULL,
- (const void **)&cert_context)) {
- char buffer[STRERROR_LEN];
- failf(data,
- "schannel: failed to extract certificate from CA file "
- "'%s': %s",
- ca_file,
- Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
- result = CURLE_SSL_CACERT_BADFILE;
- more_certs = 0;
- }
- else {
- current_ca_file_ptr = begin_cert_ptr + cert_size;
-
- /* Sanity check that the cert_context object is the right type */
- if(CERT_QUERY_CONTENT_CERT != actual_content_type) {
- failf(data,
- "schannel: unexpected content type '%d' when extracting "
- "certificate from CA file '%s'",
- actual_content_type, ca_file);
- result = CURLE_SSL_CACERT_BADFILE;
- more_certs = 0;
- }
- else {
- add_cert_result =
- CertAddCertificateContextToStore(trust_store,
- cert_context,
- CERT_STORE_ADD_ALWAYS,
- NULL);
- CertFreeCertificateContext(cert_context);
- if(!add_cert_result) {
- char buffer[STRERROR_LEN];
- failf(data,
- "schannel: failed to add certificate from CA file '%s' "
- "to certificate store: %s",
- ca_file,
- Curl_winapi_strerror(GetLastError(), buffer,
- sizeof(buffer)));
- result = CURLE_SSL_CACERT_BADFILE;
- more_certs = 0;
- }
- else {
- num_certs++;
- }
- }
- }
- }
- }
- }
-
- if(result == CURLE_OK) {
- if(!num_certs) {
- infof(data,
- "schannel: did not add any certificates from CA file '%s'\n",
- ca_file);
- }
- else {
- infof(data,
- "schannel: added %d certificate(s) from CA file '%s'\n",
- num_certs, ca_file);
- }
- }
+ result = add_certs_data_to_store(trust_store,
+ ca_file_buffer, ca_file_bufsize,
+ ca_file,
+ data);
cleanup:
if(ca_file_handle != INVALID_HANDLE_VALUE) {
@@ -389,7 +428,7 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
if(entry->dwAltNameChoice != CERT_ALT_NAME_DNS_NAME) {
continue;
}
- if(entry->pwszDNSName == NULL) {
+ if(!entry->pwszDNSName) {
infof(data, "schannel: Empty DNS name.");
continue;
}
@@ -536,27 +575,22 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data,
const CERT_CHAIN_CONTEXT *pChainContext = NULL;
HCERTCHAINENGINE cert_chain_engine = NULL;
HCERTSTORE trust_store = NULL;
-#ifndef CURL_DISABLE_PROXY
- const char * const conn_hostname = SSL_IS_PROXY() ?
- conn->http_proxy.host.name :
- conn->host.name;
-#else
- const char * const conn_hostname = conn->host.name;
-#endif
+ const char * const conn_hostname = SSL_HOST_NAME();
sspi_status =
s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&pCertContextServer);
- if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ if((sspi_status != SEC_E_OK) || !pCertContextServer) {
char buffer[STRERROR_LEN];
failf(data, "schannel: Failed to read remote certificate context: %s",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
result = CURLE_PEER_FAILED_VERIFICATION;
}
- if(result == CURLE_OK && SSL_CONN_CONFIG(CAfile) &&
+ if(result == CURLE_OK &&
+ (SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
BACKEND->use_manual_cred_validation) {
/*
* Create a chain engine that uses the certificates in the CA file as
@@ -582,8 +616,19 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data,
result = CURLE_SSL_CACERT_BADFILE;
}
else {
- result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile),
- data);
+ const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ if(ca_info_blob) {
+ result = add_certs_data_to_store(trust_store,
+ (const char *)ca_info_blob->data,
+ ca_info_blob->len,
+ "(memory blob)",
+ data);
+ }
+ else {
+ result = add_certs_file_to_store(trust_store,
+ SSL_CONN_CONFIG(CAfile),
+ data);
+ }
}
}
@@ -624,7 +669,7 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data,
NULL,
pCertContextServer->hCertStore,
&ChainPara,
- (data->set.ssl.no_revoke ? 0 :
+ (SSL_SET_OPTION(no_revoke) ? 0 :
CERT_CHAIN_REVOCATION_CHECK_CHAIN),
NULL,
&pChainContext)) {
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.c b/Utilities/cmcurl/lib/vtls/sectransp.c
index 9a8f7de8d..edd375ea7 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.c
+++ b/Utilities/cmcurl/lib/vtls/sectransp.c
@@ -67,6 +67,7 @@
#define CURL_BUILD_IOS_7 0
#define CURL_BUILD_IOS_9 0
#define CURL_BUILD_IOS_11 0
+#define CURL_BUILD_IOS_13 0
#define CURL_BUILD_MAC 1
/* This is the maximum API level we are allowed to use when building: */
#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
@@ -76,6 +77,7 @@
#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
#define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
+#define CURL_BUILD_MAC_10_15 MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
/* These macros mean "the following code is present to allow runtime backward
compatibility with at least this cat or earlier":
(You set this at build-time using the compiler command line option
@@ -91,6 +93,7 @@
#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
#define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
#define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+#define CURL_BUILD_IOS_13 __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
#define CURL_BUILD_MAC 0
#define CURL_BUILD_MAC_10_5 0
#define CURL_BUILD_MAC_10_6 0
@@ -99,6 +102,7 @@
#define CURL_BUILD_MAC_10_9 0
#define CURL_BUILD_MAC_10_11 0
#define CURL_BUILD_MAC_10_13 0
+#define CURL_BUILD_MAC_10_15 0
#define CURL_SUPPORT_MAC_10_5 0
#define CURL_SUPPORT_MAC_10_6 0
#define CURL_SUPPORT_MAC_10_7 0
@@ -138,6 +142,636 @@ struct ssl_backend_data {
size_t ssl_write_buffered_length;
};
+struct st_cipher {
+ const char *name; /* Cipher suite IANA name. It starts with "TLS_" prefix */
+ const char *alias_name; /* Alias name is the same as OpenSSL cipher name */
+ SSLCipherSuite num; /* Cipher suite code/number defined in IANA registry */
+ bool weak; /* Flag to mark cipher as weak based on previous implementation
+ of Secure Transport back-end by CURL */
+};
+
+/* Macro to initialize st_cipher data structure: stringify id to name, cipher
+ number/id, 'weak' suite flag
+ */
+#define CIPHER_DEF(num, alias, weak) \
+ { #num, alias, num, weak }
+
+/*
+ Macro to initialize st_cipher data structure with name, code (IANA cipher
+ number/id value), and 'weak' suite flag. The first 28 cipher suite numbers
+ have the same IANA code for both SSL and TLS standards: numbers 0x0000 to
+ 0x001B. They have different names though. The first 4 letters of the cipher
+ suite name are the protocol name: "SSL_" or "TLS_", rest of the IANA name is
+ the same for both SSL and TLS cipher suite name.
+ The second part of the problem is that macOS/iOS SDKs don't define all TLS
+ codes but only 12 of them. The SDK defines all SSL codes though, i.e. SSL_NUM
+ constant is always defined for those 28 ciphers while TLS_NUM is defined only
+ for 12 of the first 28 ciphers. Those 12 TLS cipher codes match to
+ corresponding SSL enum value and represent the same cipher suite. Therefore
+ we'll use the SSL enum value for those cipher suites because it is defined
+ for all 28 of them.
+ We make internal data consistent and based on TLS names, i.e. all st_cipher
+ item names start with the "TLS_" prefix.
+ Summarizing all the above, those 28 first ciphers are presented in our table
+ with both TLS and SSL names. Their cipher numbers are assigned based on the
+ SDK enum value for the SSL cipher, which matches to IANA TLS number.
+ */
+#define CIPHER_DEF_SSLTLS(num_wo_prefix, alias, weak) \
+ { "TLS_" #num_wo_prefix, alias, SSL_##num_wo_prefix, weak }
+
+/*
+ Cipher suites were marked as weak based on the following:
+ RC4 encryption - rfc7465, the document contains a list of deprecated ciphers.
+ Marked in the code below as weak.
+ RC2 encryption - many mentions, was found vulnerable to a relatively easy
+ attack https://link.springer.com/chapter/10.1007%2F3-540-69710-1_14
+ Marked in the code below as weak.
+ DES and IDEA encryption - rfc5469, has a list of deprecated ciphers.
+ Marked in the code below as weak.
+ Anonymous Diffie-Hellman authentication and anonymous elliptic curve
+ Diffie-Hellman - vulnerable to a man-in-the-middle attack. Deprecated by
+ RFC 4346 aka TLS 1.1 (section A.5, page 60)
+ Null bulk encryption suites - not encrypted communication
+ Export ciphers, i.e. ciphers with restrictions to be used outside the US for
+ software exported to some countries, they were excluded from TLS 1.1
+ version. More precisely, they were noted as ciphers which MUST NOT be
+ negotiated in RFC 4346 aka TLS 1.1 (section A.5, pages 60 and 61).
+ All of those filters were considered weak because they contain a weak
+ algorithm like DES, RC2 or RC4, and already considered weak by other
+ criteria.
+ 3DES - NIST deprecated it and is going to retire it by 2023
+ https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA
+ OpenSSL https://www.openssl.org/blog/blog/2016/08/24/sweet32/ also
+ deprecated those ciphers. Some other libraries also consider it
+ vulnerable or at least not strong enough.
+
+ CBC ciphers are vulnerable with SSL3.0 and TLS1.0:
+ https://www.cisco.com/c/en/us/support/docs/security/email-security-appliance
+ /118518-technote-esa-00.html
+ We don't take care of this issue because it is resolved by later TLS
+ versions and for us, it requires more complicated checks, we need to
+ check a protocol version also. Vulnerability doesn't look very critical
+ and we do not filter out those cipher suites.
+ */
+
+#define CIPHER_WEAK_NOT_ENCRYPTED TRUE
+#define CIPHER_WEAK_RC_ENCRYPTION TRUE
+#define CIPHER_WEAK_DES_ENCRYPTION TRUE
+#define CIPHER_WEAK_IDEA_ENCRYPTION TRUE
+#define CIPHER_WEAK_ANON_AUTH TRUE
+#define CIPHER_WEAK_3DES_ENCRYPTION TRUE
+#define CIPHER_STRONG_ENOUGH FALSE
+
+/* Please do not change the order of the first ciphers available for SSL.
+ Do not insert and do not delete any of them. Code below
+ depends on their order and continuity.
+ If you add a new cipher, please maintain order by number, i.e.
+ insert in between existing items to appropriate place based on
+ cipher suite IANA number
+*/
+const static struct st_cipher ciphertable[] = {
+ /* SSL version 3.0 and initial TLS 1.0 cipher suites.
+ Defined since SDK 10.2.8 */
+ CIPHER_DEF_SSLTLS(NULL_WITH_NULL_NULL, /* 0x0000 */
+ NULL,
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF_SSLTLS(RSA_WITH_NULL_MD5, /* 0x0001 */
+ "NULL-MD5",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF_SSLTLS(RSA_WITH_NULL_SHA, /* 0x0002 */
+ "NULL-SHA",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC4_40_MD5, /* 0x0003 */
+ "EXP-RC4-MD5",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_MD5, /* 0x0004 */
+ "RC4-MD5",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_SHA, /* 0x0005 */
+ "RC4-SHA",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* 0x0006 */
+ "EXP-RC2-CBC-MD5",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(RSA_WITH_IDEA_CBC_SHA, /* 0x0007 */
+ "IDEA-CBC-SHA",
+ CIPHER_WEAK_IDEA_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0008 */
+ "EXP-DES-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(RSA_WITH_DES_CBC_SHA, /* 0x0009 */
+ "DES-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(RSA_WITH_3DES_EDE_CBC_SHA, /* 0x000A */
+ "DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DH_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x000B */
+ "EXP-DH-DSS-DES-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DH_DSS_WITH_DES_CBC_SHA, /* 0x000C */
+ "DH-DSS-DES-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DH_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x000D */
+ "DH-DSS-DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DH_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x000E */
+ "EXP-DH-RSA-DES-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DH_RSA_WITH_DES_CBC_SHA, /* 0x000F */
+ "DH-RSA-DES-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0010 */
+ "DH-RSA-DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x0011 */
+ "EXP-EDH-DSS-DES-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DHE_DSS_WITH_DES_CBC_SHA, /* 0x0012 */
+ "EDH-DSS-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x0013 */
+ "DHE-DSS-DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0014 */
+ "EXP-EDH-RSA-DES-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DHE_RSA_WITH_DES_CBC_SHA, /* 0x0015 */
+ "EDH-RSA-DES-CBC-SHA",
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0016 */
+ "DHE-RSA-DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_RC4_40_MD5, /* 0x0017 */
+ "EXP-ADH-RC4-MD5",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF_SSLTLS(DH_anon_WITH_RC4_128_MD5, /* 0x0018 */
+ "ADH-RC4-MD5",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_DES40_CBC_SHA, /* 0x0019 */
+ "EXP-ADH-DES-CBC-SHA",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF_SSLTLS(DH_anon_WITH_DES_CBC_SHA, /* 0x001A */
+ "ADH-DES-CBC-SHA",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF_SSLTLS(DH_anon_WITH_3DES_EDE_CBC_SHA, /* 0x001B */
+ "ADH-DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* 0x001C */
+ NULL,
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* 0x001D */
+ NULL,
+ CIPHER_STRONG_ENOUGH),
+
+#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
+ /* RFC 4785 - Pre-Shared Key (PSK) Ciphersuites with NULL Encryption */
+ CIPHER_DEF(TLS_PSK_WITH_NULL_SHA, /* 0x002C */
+ "PSK-NULL-SHA",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA, /* 0x002D */
+ "DHE-PSK-NULL-SHA",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA, /* 0x002E */
+ "RSA-PSK-NULL-SHA",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
+
+ /* TLS addenda using AES, per RFC 3268. Defined since SDK 10.4u */
+ CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA, /* 0x002F */
+ "AES128-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA, /* 0x0030 */
+ "DH-DSS-AES128-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA, /* 0x0031 */
+ "DH-RSA-AES128-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* 0x0032 */
+ "DHE-DSS-AES128-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* 0x0033 */
+ "DHE-RSA-AES128-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA, /* 0x0034 */
+ "ADH-AES128-SHA",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA, /* 0x0035 */
+ "AES256-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA, /* 0x0036 */
+ "DH-DSS-AES256-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA, /* 0x0037 */
+ "DH-RSA-AES256-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* 0x0038 */
+ "DHE-DSS-AES256-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* 0x0039 */
+ "DHE-RSA-AES256-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA, /* 0x003A */
+ "ADH-AES256-SHA",
+ CIPHER_WEAK_ANON_AUTH),
+
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ /* TLS 1.2 addenda, RFC 5246 */
+ /* Server provided RSA certificate for key exchange. */
+ CIPHER_DEF(TLS_RSA_WITH_NULL_SHA256, /* 0x003B */
+ "NULL-SHA256",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA256, /* 0x003C */
+ "AES128-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA256, /* 0x003D */
+ "AES256-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ /* Server-authenticated (and optionally client-authenticated)
+ Diffie-Hellman. */
+ CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA256, /* 0x003E */
+ "DH-DSS-AES128-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA256, /* 0x003F */
+ "DH-RSA-AES128-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, /* 0x0040 */
+ "DHE-DSS-AES128-SHA256",
+ CIPHER_STRONG_ENOUGH),
+
+ /* TLS 1.2 addenda, RFC 5246 */
+ CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, /* 0x0067 */
+ "DHE-RSA-AES128-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA256, /* 0x0068 */
+ "DH-DSS-AES256-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA256, /* 0x0069 */
+ "DH-RSA-AES256-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, /* 0x006A */
+ "DHE-DSS-AES256-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, /* 0x006B */
+ "DHE-RSA-AES256-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA256, /* 0x006C */
+ "ADH-AES128-SHA256",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA256, /* 0x006D */
+ "ADH-AES256-SHA256",
+ CIPHER_WEAK_ANON_AUTH),
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+
+#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
+ /* Addendum from RFC 4279, TLS PSK */
+ CIPHER_DEF(TLS_PSK_WITH_RC4_128_SHA, /* 0x008A */
+ "PSK-RC4-SHA",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF(TLS_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008B */
+ "PSK-3DES-EDE-CBC-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA, /* 0x008C */
+ "PSK-AES128-CBC-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA, /* 0x008D */
+ "PSK-AES256-CBC-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_RC4_128_SHA, /* 0x008E */
+ "DHE-PSK-RC4-SHA",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008F */
+ "DHE-PSK-3DES-EDE-CBC-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA, /* 0x0090 */
+ "DHE-PSK-AES128-CBC-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA, /* 0x0091 */
+ "DHE-PSK-AES256-CBC-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_RC4_128_SHA, /* 0x0092 */
+ "RSA-PSK-RC4-SHA",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x0093 */
+ "RSA-PSK-3DES-EDE-CBC-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA, /* 0x0094 */
+ "RSA-PSK-AES128-CBC-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA, /* 0x0095 */
+ "RSA-PSK-AES256-CBC-SHA",
+ CIPHER_STRONG_ENOUGH),
+#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
+
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ /* Addenda from rfc 5288 AES Galois Counter Mode (GCM) Cipher Suites
+ for TLS. */
+ CIPHER_DEF(TLS_RSA_WITH_AES_128_GCM_SHA256, /* 0x009C */
+ "AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_RSA_WITH_AES_256_GCM_SHA384, /* 0x009D */
+ "AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, /* 0x009E */
+ "DHE-RSA-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, /* 0x009F */
+ "DHE-RSA-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_GCM_SHA256, /* 0x00A0 */
+ "DH-RSA-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_GCM_SHA384, /* 0x00A1 */
+ "DH-RSA-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A2 */
+ "DHE-DSS-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A3 */
+ "DHE-DSS-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A4 */
+ "DH-DSS-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A5 */
+ "DH-DSS-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DH_anon_WITH_AES_128_GCM_SHA256, /* 0x00A6 */
+ "ADH-AES128-GCM-SHA256",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF(TLS_DH_anon_WITH_AES_256_GCM_SHA384, /* 0x00A7 */
+ "ADH-AES256-GCM-SHA384",
+ CIPHER_WEAK_ANON_AUTH),
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+
+#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
+ /* RFC 5487 - PSK with SHA-256/384 and AES GCM */
+ CIPHER_DEF(TLS_PSK_WITH_AES_128_GCM_SHA256, /* 0x00A8 */
+ "PSK-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_PSK_WITH_AES_256_GCM_SHA384, /* 0x00A9 */
+ "PSK-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AA */
+ "DHE-PSK-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AB */
+ "DHE-PSK-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AC */
+ "RSA-PSK-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AD */
+ "RSA-PSK-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA256, /* 0x00AE */
+ "PSK-AES128-CBC-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA384, /* 0x00AF */
+ "PSK-AES256-CBC-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_PSK_WITH_NULL_SHA256, /* 0x00B0 */
+ "PSK-NULL-SHA256",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_PSK_WITH_NULL_SHA384, /* 0x00B1 */
+ "PSK-NULL-SHA384",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B2 */
+ "DHE-PSK-AES128-CBC-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B3 */
+ "DHE-PSK-AES256-CBC-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA256, /* 0x00B4 */
+ "DHE-PSK-NULL-SHA256",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA384, /* 0x00B5 */
+ "DHE-PSK-NULL-SHA384",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B6 */
+ "RSA-PSK-AES128-CBC-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B7 */
+ "RSA-PSK-AES256-CBC-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA256, /* 0x00B8 */
+ "RSA-PSK-NULL-SHA256",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA384, /* 0x00B9 */
+ "RSA-PSK-NULL-SHA384",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
+
+ /* RFC 5746 - Secure Renegotiation. This is not a real suite,
+ it is a response to initiate negotiation again */
+ CIPHER_DEF(TLS_EMPTY_RENEGOTIATION_INFO_SCSV, /* 0x00FF */
+ NULL,
+ CIPHER_STRONG_ENOUGH),
+
+#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+ /* TLS 1.3 standard cipher suites for ChaCha20+Poly1305.
+ Note: TLS 1.3 ciphersuites do not specify the key exchange
+ algorithm -- they only specify the symmetric ciphers.
+ Cipher alias name matches to OpenSSL cipher name, and for
+ TLS 1.3 ciphers */
+ CIPHER_DEF(TLS_AES_128_GCM_SHA256, /* 0x1301 */
+ NULL, /* The OpenSSL cipher name matches to the IANA name */
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_AES_256_GCM_SHA384, /* 0x1302 */
+ NULL, /* The OpenSSL cipher name matches to the IANA name */
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_CHACHA20_POLY1305_SHA256, /* 0x1303 */
+ NULL, /* The OpenSSL cipher name matches to the IANA name */
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_AES_128_CCM_SHA256, /* 0x1304 */
+ NULL, /* The OpenSSL cipher name matches to the IANA name */
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_AES_128_CCM_8_SHA256, /* 0x1305 */
+ NULL, /* The OpenSSL cipher name matches to the IANA name */
+ CIPHER_STRONG_ENOUGH),
+#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+
+#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
+ /* ECDSA addenda, RFC 4492 */
+ CIPHER_DEF(TLS_ECDH_ECDSA_WITH_NULL_SHA, /* 0xC001 */
+ "ECDH-ECDSA-NULL-SHA",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_ECDH_ECDSA_WITH_RC4_128_SHA, /* 0xC002 */
+ "ECDH-ECDSA-RC4-SHA",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC003 */
+ "ECDH-ECDSA-DES-CBC3-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC004 */
+ "ECDH-ECDSA-AES128-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC005 */
+ "ECDH-ECDSA-AES256-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_NULL_SHA, /* 0xC006 */
+ "ECDHE-ECDSA-NULL-SHA",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, /* 0xC007 */
+ "ECDHE-ECDSA-RC4-SHA",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC008 */
+ "ECDHE-ECDSA-DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC009 */
+ "ECDHE-ECDSA-AES128-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC00A */
+ "ECDHE-ECDSA-AES256-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_RSA_WITH_NULL_SHA, /* 0xC00B */
+ "ECDH-RSA-NULL-SHA",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_ECDH_RSA_WITH_RC4_128_SHA, /* 0xC00C */
+ "ECDH-RSA-RC4-SHA",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC00D */
+ "ECDH-RSA-DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* 0xC00E */
+ "ECDH-RSA-AES128-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* 0xC00F */
+ "ECDH-RSA-AES256-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_NULL_SHA, /* 0xC010 */
+ "ECDHE-RSA-NULL-SHA",
+ CIPHER_WEAK_NOT_ENCRYPTED),
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_RC4_128_SHA, /* 0xC011 */
+ "ECDHE-RSA-RC4-SHA",
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC012 */
+ "ECDHE-RSA-DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* 0xC013 */
+ "ECDHE-RSA-AES128-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, /* 0xC014 */
+ "ECDHE-RSA-AES256-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_anon_WITH_NULL_SHA, /* 0xC015 */
+ "AECDH-NULL-SHA",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF(TLS_ECDH_anon_WITH_RC4_128_SHA, /* 0xC016 */
+ "AECDH-RC4-SHA",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, /* 0xC017 */
+ "AECDH-DES-CBC3-SHA",
+ CIPHER_WEAK_3DES_ENCRYPTION),
+ CIPHER_DEF(TLS_ECDH_anon_WITH_AES_128_CBC_SHA, /* 0xC018 */
+ "AECDH-AES128-SHA",
+ CIPHER_WEAK_ANON_AUTH),
+ CIPHER_DEF(TLS_ECDH_anon_WITH_AES_256_CBC_SHA, /* 0xC019 */
+ "AECDH-AES256-SHA",
+ CIPHER_WEAK_ANON_AUTH),
+#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
+
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with
+ HMAC SHA-256/384. */
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC023 */
+ "ECDHE-ECDSA-AES128-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC024 */
+ "ECDHE-ECDSA-AES256-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC025 */
+ "ECDH-ECDSA-AES128-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC026 */
+ "ECDH-ECDSA-AES256-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, /* 0xC027 */
+ "ECDHE-RSA-AES128-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, /* 0xC028 */
+ "ECDHE-RSA-AES256-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, /* 0xC029 */
+ "ECDH-RSA-AES128-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, /* 0xC02A */
+ "ECDH-RSA-AES256-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with
+ SHA-256/384 and AES Galois Counter Mode (GCM) */
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02B */
+ "ECDHE-ECDSA-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02C */
+ "ECDHE-ECDSA-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02D */
+ "ECDH-ECDSA-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02E */
+ "ECDH-ECDSA-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, /* 0xC02F */
+ "ECDHE-RSA-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, /* 0xC030 */
+ "ECDHE-RSA-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, /* 0xC031 */
+ "ECDH-RSA-AES128-GCM-SHA256",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, /* 0xC032 */
+ "ECDH-RSA-AES256-GCM-SHA384",
+ CIPHER_STRONG_ENOUGH),
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+
+#if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13
+ /* ECDHE_PSK Cipher Suites for Transport Layer Security (TLS), RFC 5489 */
+ CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, /* 0xC035 */
+ "ECDHE-PSK-AES128-CBC-SHA",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, /* 0xC036 */
+ "ECDHE-PSK-AES256-CBC-SHA",
+ CIPHER_STRONG_ENOUGH),
+#endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */
+
+#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+ /* Addenda from rfc 7905 ChaCha20-Poly1305 Cipher Suites for
+ Transport Layer Security (TLS). */
+ CIPHER_DEF(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA8 */
+ "ECDHE-RSA-CHACHA20-POLY1305",
+ CIPHER_STRONG_ENOUGH),
+ CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA9 */
+ "ECDHE-ECDSA-CHACHA20-POLY1305",
+ CIPHER_STRONG_ENOUGH),
+#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+
+#if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13
+ /* ChaCha20-Poly1305 Cipher Suites for Transport Layer Security (TLS),
+ RFC 7905 */
+ CIPHER_DEF(TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCAB */
+ "PSK-CHACHA20-POLY1305",
+ CIPHER_STRONG_ENOUGH),
+#endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */
+
+ /* Tags for SSL 2 cipher kinds which are not specified for SSL 3.
+ Defined since SDK 10.2.8 */
+ CIPHER_DEF(SSL_RSA_WITH_RC2_CBC_MD5, /* 0xFF80 */
+ NULL,
+ CIPHER_WEAK_RC_ENCRYPTION),
+ CIPHER_DEF(SSL_RSA_WITH_IDEA_CBC_MD5, /* 0xFF81 */
+ NULL,
+ CIPHER_WEAK_IDEA_ENCRYPTION),
+ CIPHER_DEF(SSL_RSA_WITH_DES_CBC_MD5, /* 0xFF82 */
+ NULL,
+ CIPHER_WEAK_DES_ENCRYPTION),
+ CIPHER_DEF(SSL_RSA_WITH_3DES_EDE_CBC_MD5, /* 0xFF83 */
+ NULL,
+ CIPHER_WEAK_3DES_ENCRYPTION),
+};
+
+#define NUM_OF_CIPHERS sizeof(ciphertable)/sizeof(ciphertable[0])
+
+
/* pinned public key support tests */
/* version 1 supports macOS 10.12+ and iOS 10+ */
@@ -295,586 +929,23 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
-CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher)
-{
- switch(cipher) {
- /* SSL version 3.0 */
- case SSL_RSA_WITH_NULL_MD5:
- return "SSL_RSA_WITH_NULL_MD5";
- break;
- case SSL_RSA_WITH_NULL_SHA:
- return "SSL_RSA_WITH_NULL_SHA";
- break;
- case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
- return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
- break;
- case SSL_RSA_WITH_RC4_128_MD5:
- return "SSL_RSA_WITH_RC4_128_MD5";
- break;
- case SSL_RSA_WITH_RC4_128_SHA:
- return "SSL_RSA_WITH_RC4_128_SHA";
- break;
- case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
- return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
- break;
- case SSL_RSA_WITH_IDEA_CBC_SHA:
- return "SSL_RSA_WITH_IDEA_CBC_SHA";
- break;
- case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_RSA_WITH_DES_CBC_SHA:
- return "SSL_RSA_WITH_DES_CBC_SHA";
- break;
- case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
- return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DH_DSS_WITH_DES_CBC_SHA:
- return "SSL_DH_DSS_WITH_DES_CBC_SHA";
- break;
- case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DH_RSA_WITH_DES_CBC_SHA:
- return "SSL_DH_RSA_WITH_DES_CBC_SHA";
- break;
- case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DHE_DSS_WITH_DES_CBC_SHA:
- return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
- break;
- case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DHE_RSA_WITH_DES_CBC_SHA:
- return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
- break;
- case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
- return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
- break;
- case SSL_DH_anon_WITH_RC4_128_MD5:
- return "SSL_DH_anon_WITH_RC4_128_MD5";
- break;
- case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DH_anon_WITH_DES_CBC_SHA:
- return "SSL_DH_anon_WITH_DES_CBC_SHA";
- break;
- case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
- return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
- break;
- case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
- return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
- break;
- /* TLS 1.0 with AES (RFC 3268)
- (Apparently these are used in SSLv3 implementations as well.) */
- case TLS_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_128_CBC_SHA:
- return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
- break;
- case TLS_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_256_CBC_SHA:
- return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
- break;
- /* SSL version 2.0 */
- case SSL_RSA_WITH_RC2_CBC_MD5:
- return "SSL_RSA_WITH_RC2_CBC_MD5";
- break;
- case SSL_RSA_WITH_IDEA_CBC_MD5:
- return "SSL_RSA_WITH_IDEA_CBC_MD5";
- break;
- case SSL_RSA_WITH_DES_CBC_MD5:
- return "SSL_RSA_WITH_DES_CBC_MD5";
- break;
- case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
- return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
- break;
- }
- return "SSL_NULL_WITH_NULL_NULL";
-}
-
CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
{
- switch(cipher) {
- /* TLS 1.0 with AES (RFC 3268) */
- case TLS_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_128_CBC_SHA:
- return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
- break;
- case TLS_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_256_CBC_SHA:
- return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
- break;
-#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
- /* TLS 1.0 with ECDSA (RFC 4492) */
- case TLS_ECDH_ECDSA_WITH_NULL_SHA:
- return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
- break;
- case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
- break;
- case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
- return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
- return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
- return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_ECDH_RSA_WITH_NULL_SHA:
- return "TLS_ECDH_RSA_WITH_NULL_SHA";
- break;
- case TLS_ECDH_RSA_WITH_RC4_128_SHA:
- return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
- break;
- case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_NULL_SHA:
- return "TLS_ECDHE_RSA_WITH_NULL_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_ECDH_anon_WITH_NULL_SHA:
- return "TLS_ECDH_anon_WITH_NULL_SHA";
- break;
- case TLS_ECDH_anon_WITH_RC4_128_SHA:
- return "TLS_ECDH_anon_WITH_RC4_128_SHA";
- break;
- case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
- return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
- return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
- break;
-#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
-#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- /* TLS 1.2 (RFC 5246) */
- case TLS_RSA_WITH_NULL_MD5:
- return "TLS_RSA_WITH_NULL_MD5";
- break;
- case TLS_RSA_WITH_NULL_SHA:
- return "TLS_RSA_WITH_NULL_SHA";
- break;
- case TLS_RSA_WITH_RC4_128_MD5:
- return "TLS_RSA_WITH_RC4_128_MD5";
- break;
- case TLS_RSA_WITH_RC4_128_SHA:
- return "TLS_RSA_WITH_RC4_128_SHA";
- break;
- case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_RSA_WITH_NULL_SHA256:
- return "TLS_RSA_WITH_NULL_SHA256";
- break;
- case TLS_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_RSA_WITH_AES_256_CBC_SHA256:
- return "TLS_RSA_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
- return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
- return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
- return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
- return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
- return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
- return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DH_anon_WITH_RC4_128_MD5:
- return "TLS_DH_anon_WITH_RC4_128_MD5";
- break;
- case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
- return "TLS_DH_anon_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
- return "TLS_DH_anon_WITH_AES_256_CBC_SHA256";
- break;
- /* TLS 1.2 with AES GCM (RFC 5288) */
- case TLS_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
- return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
- return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
- return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
- return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DH_anon_WITH_AES_128_GCM_SHA256:
- return "TLS_DH_anon_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
- return "TLS_DH_anon_WITH_AES_256_GCM_SHA384";
- break;
- /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
- return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
- return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
- return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_EMPTY_RENEGOTIATION_INFO_SCSV:
- return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
- break;
-#else
- case SSL_RSA_WITH_NULL_MD5:
- return "TLS_RSA_WITH_NULL_MD5";
- break;
- case SSL_RSA_WITH_NULL_SHA:
- return "TLS_RSA_WITH_NULL_SHA";
- break;
- case SSL_RSA_WITH_RC4_128_MD5:
- return "TLS_RSA_WITH_RC4_128_MD5";
- break;
- case SSL_RSA_WITH_RC4_128_SHA:
- return "TLS_RSA_WITH_RC4_128_SHA";
- break;
- case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DH_anon_WITH_RC4_128_MD5:
- return "TLS_DH_anon_WITH_RC4_128_MD5";
- break;
- case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
- break;
-#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
-#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
- /* TLS PSK (RFC 4279): */
- case TLS_PSK_WITH_RC4_128_SHA:
- return "TLS_PSK_WITH_RC4_128_SHA";
- break;
- case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
- return "TLS_PSK_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_PSK_WITH_AES_128_CBC_SHA:
- return "TLS_PSK_WITH_AES_128_CBC_SHA";
- break;
- case TLS_PSK_WITH_AES_256_CBC_SHA:
- return "TLS_PSK_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_PSK_WITH_RC4_128_SHA:
- return "TLS_DHE_PSK_WITH_RC4_128_SHA";
- break;
- case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
- break;
- case TLS_RSA_PSK_WITH_RC4_128_SHA:
- return "TLS_RSA_PSK_WITH_RC4_128_SHA";
- break;
- case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
- return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
- return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
- break;
- case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
- return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
- break;
- /* More TLS PSK (RFC 4785): */
- case TLS_PSK_WITH_NULL_SHA:
- return "TLS_PSK_WITH_NULL_SHA";
- break;
- case TLS_DHE_PSK_WITH_NULL_SHA:
- return "TLS_DHE_PSK_WITH_NULL_SHA";
- break;
- case TLS_RSA_PSK_WITH_NULL_SHA:
- return "TLS_RSA_PSK_WITH_NULL_SHA";
- break;
- /* Even more TLS PSK (RFC 5487): */
- case TLS_PSK_WITH_AES_128_GCM_SHA256:
- return "TLS_PSK_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_PSK_WITH_AES_256_GCM_SHA384:
- return "TLS_PSK_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
- return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
- return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
- return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
- return "TLS_PSK_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_PSK_WITH_AES_128_CBC_SHA256:
- return "TLS_PSK_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_PSK_WITH_AES_256_CBC_SHA384:
- return "TLS_PSK_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_PSK_WITH_NULL_SHA256:
- return "TLS_PSK_WITH_NULL_SHA256";
- break;
- case TLS_PSK_WITH_NULL_SHA384:
- return "TLS_PSK_WITH_NULL_SHA384";
- break;
- case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
- return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
- return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_DHE_PSK_WITH_NULL_SHA256:
- return "TLS_DHE_PSK_WITH_NULL_SHA256";
- break;
- case TLS_DHE_PSK_WITH_NULL_SHA384:
- return "TLS_RSA_PSK_WITH_NULL_SHA384";
- break;
- case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
- return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
- return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_RSA_PSK_WITH_NULL_SHA256:
- return "TLS_RSA_PSK_WITH_NULL_SHA256";
- break;
- case TLS_RSA_PSK_WITH_NULL_SHA384:
- return "TLS_RSA_PSK_WITH_NULL_SHA384";
- break;
-#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
- /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */
- case TLS_AES_128_GCM_SHA256:
- return "TLS_AES_128_GCM_SHA256";
- break;
- case TLS_AES_256_GCM_SHA384:
- return "TLS_AES_256_GCM_SHA384";
- break;
- case TLS_CHACHA20_POLY1305_SHA256:
- return "TLS_CHACHA20_POLY1305_SHA256";
- break;
- case TLS_AES_128_CCM_SHA256:
- return "TLS_AES_128_CCM_SHA256";
- break;
- case TLS_AES_128_CCM_8_SHA256:
- return "TLS_AES_128_CCM_8_SHA256";
- break;
- case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
- break;
- case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
- break;
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+ /* The first ciphers in the ciphertable are continuos. Here we do small
+ optimization and instead of loop directly get SSL name by cipher number.
+ */
+ if(cipher <= SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA) {
+ return ciphertable[cipher].name;
+ }
+ /* Iterate through the rest of the ciphers */
+ for(size_t i = SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA + 1;
+ i < NUM_OF_CIPHERS;
+ ++i) {
+ if(ciphertable[i].num == cipher) {
+ return ciphertable[i].name;
+ }
}
- return "TLS_NULL_WITH_NULL_NULL";
+ return ciphertable[SSL_NULL_WITH_NULL_NULL].name;
}
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
@@ -1087,12 +1158,14 @@ static OSStatus CopyIdentityWithLabel(char *label,
(SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
err = SecIdentityCopyCertificate(identity, &cert);
if(err == noErr) {
+ OSStatus copy_status = noErr;
#if CURL_BUILD_IOS
common_name = SecCertificateCopySubjectSummary(cert);
#elif CURL_BUILD_MAC_10_7
- SecCertificateCopyCommonName(cert, &common_name);
+ copy_status = SecCertificateCopyCommonName(cert, &common_name);
#endif
- if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
+ if(copy_status == noErr &&
+ CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
CFRelease(cert);
CFRelease(common_name);
CFRetain(identity);
@@ -1253,7 +1326,7 @@ CF_INLINE bool is_file(const char *filename)
{
struct_stat st;
- if(filename == NULL)
+ if(!filename)
return false;
if(stat(filename, &st) == 0)
@@ -1386,6 +1459,200 @@ set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
+static bool is_cipher_suite_strong(SSLCipherSuite suite_num)
+{
+ for(size_t i = 0; i < NUM_OF_CIPHERS; ++i) {
+ if(ciphertable[i].num == suite_num) {
+ return !ciphertable[i].weak;
+ }
+ }
+ /* If the cipher is not in our list, assume it is a new one
+ and therefore strong. Previous implementation was the same,
+ if cipher suite is not in the list, it was considered strong enough */
+ return true;
+}
+
+static bool is_separator(char c)
+{
+ /* Return whether character is a cipher list separator. */
+ switch(c) {
+ case ' ':
+ case '\t':
+ case ':':
+ case ',':
+ case ';':
+ return true;
+ }
+ return false;
+}
+
+static CURLcode sectransp_set_default_ciphers(struct Curl_easy *data,
+ SSLContextRef ssl_ctx)
+{
+ size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
+ SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
+ OSStatus err = noErr;
+
+#if CURL_BUILD_MAC
+ int darwinver_maj = 0, darwinver_min = 0;
+
+ GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
+#endif /* CURL_BUILD_MAC */
+
+ /* Disable cipher suites that ST supports but are not safe. These ciphers
+ are unlikely to be used in any case since ST gives other ciphers a much
+ higher priority, but it's probably better that we not connect at all than
+ to give the user a false sense of security if the server only supports
+ insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
+ err = SSLGetNumberSupportedCiphers(ssl_ctx, &all_ciphers_count);
+ if(err != noErr) {
+ failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d",
+ err);
+ return CURLE_SSL_CIPHER;
+ }
+ all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
+ if(!all_ciphers) {
+ failf(data, "SSL: Failed to allocate memory for all ciphers");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
+ if(!allowed_ciphers) {
+ Curl_safefree(all_ciphers);
+ failf(data, "SSL: Failed to allocate memory for allowed ciphers");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ err = SSLGetSupportedCiphers(ssl_ctx, all_ciphers,
+ &all_ciphers_count);
+ if(err != noErr) {
+ Curl_safefree(all_ciphers);
+ Curl_safefree(allowed_ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+ for(i = 0UL ; i < all_ciphers_count ; i++) {
+#if CURL_BUILD_MAC
+ /* There's a known bug in early versions of Mountain Lion where ST's ECC
+ ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
+ Work around the problem here by disabling those ciphers if we are
+ running in an affected version of OS X. */
+ if(darwinver_maj == 12 && darwinver_min <= 3 &&
+ all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
+ continue;
+ }
+#endif /* CURL_BUILD_MAC */
+ if(is_cipher_suite_strong(all_ciphers[i])) {
+ allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
+ }
+ }
+ err = SSLSetEnabledCiphers(ssl_ctx, allowed_ciphers,
+ allowed_ciphers_count);
+ Curl_safefree(all_ciphers);
+ Curl_safefree(allowed_ciphers);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
+ return CURLE_SSL_CIPHER;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
+ SSLContextRef ssl_ctx,
+ const char *ciphers)
+{
+ size_t ciphers_count = 0;
+ const char *cipher_start = ciphers;
+ OSStatus err = noErr;
+ SSLCipherSuite selected_ciphers[NUM_OF_CIPHERS];
+
+ if(!ciphers)
+ return CURLE_OK;
+
+ while(is_separator(*ciphers)) /* Skip initial separators. */
+ ciphers++;
+ if(!*ciphers)
+ return CURLE_OK;
+
+ cipher_start = ciphers;
+ while(*cipher_start && ciphers_count < NUM_OF_CIPHERS) {
+ bool cipher_found = FALSE;
+ size_t cipher_len = 0;
+ const char *cipher_end = NULL;
+ bool tls_name = FALSE;
+
+ /* Skip separators */
+ while(is_separator(*cipher_start))
+ cipher_start++;
+ if(*cipher_start == '\0') {
+ break;
+ }
+ /* Find last position of a cipher in the ciphers string */
+ cipher_end = cipher_start;
+ while (*cipher_end != '\0' && !is_separator(*cipher_end)) {
+ ++cipher_end;
+ }
+
+ /* IANA cipher names start with the TLS_ or SSL_ prefix.
+ If the 4th symbol of the cipher is '_' we look for a cipher in the
+ table by its (TLS) name.
+ Otherwise, we try to match cipher by an alias. */
+ if(cipher_start[3] == '_') {
+ tls_name = TRUE;
+ }
+ /* Iterate through the cipher table and look for the cipher, starting
+ the cipher number 0x01 because the 0x00 is not the real cipher */
+ cipher_len = cipher_end - cipher_start;
+ for(size_t i = 1; i < NUM_OF_CIPHERS; ++i) {
+ const char *table_cipher_name = NULL;
+ if(tls_name) {
+ table_cipher_name = ciphertable[i].name;
+ }
+ else if(ciphertable[i].alias_name != NULL) {
+ table_cipher_name = ciphertable[i].alias_name;
+ }
+ else {
+ continue;
+ }
+ /* Compare a part of the string between separators with a cipher name
+ in the table and make sure we matched the whole cipher name */
+ if(strncmp(cipher_start, table_cipher_name, cipher_len) == 0
+ && table_cipher_name[cipher_len] == '\0') {
+ selected_ciphers[ciphers_count] = ciphertable[i].num;
+ ++ciphers_count;
+ cipher_found = TRUE;
+ break;
+ }
+ }
+ if(!cipher_found) {
+ /* It would be more human-readable if we print the wrong cipher name
+ but we don't want to allocate any additional memory and copy the name
+ into it, then add it into logs.
+ Also, we do not modify an original cipher list string. We just point
+ to positions where cipher starts and ends in the cipher list string.
+ The message is a bit cryptic and longer than necessary but can be
+ understood by humans. */
+ failf(data, "SSL: cipher string \"%s\" contains unsupported cipher name"
+ " starting position %d and ending position %d",
+ ciphers,
+ cipher_start - ciphers,
+ cipher_end - ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+ if(*cipher_end) {
+ cipher_start = cipher_end + 1;
+ }
+ else {
+ break;
+ }
+ }
+ /* All cipher suites in the list are found. Report to logs as-is */
+ infof(data, "SSL: Setting cipher suites list \"%s\"\n", ciphers);
+
+ err = SSLSetEnabledCiphers(ssl_ctx, selected_ciphers, ciphers_count);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
+ return CURLE_SSL_CIPHER;
+ }
+ return CURLE_OK;
+}
static CURLcode sectransp_connect_step1(struct Curl_easy *data,
struct connectdata *conn,
@@ -1394,26 +1661,22 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
- const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
- const struct curl_blob *ssl_cablob = NULL;
+ const struct curl_blob *ssl_cablob = SSL_CONN_CONFIG(ca_info_blob);
+ const char * const ssl_cafile =
+ /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+ (ssl_cablob ? NULL : SSL_CONN_CONFIG(CAfile));
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
-#else
- const char * const hostname = conn->host.name;
- const long int port = conn->remote_port;
-#endif
+ bool isproxy = SSL_IS_PROXY();
+ const char * const hostname = SSL_HOST_NAME();
+ const long int port = SSL_HOST_PORT();
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
struct in_addr addr;
#endif /* ENABLE_IPV6 */
- size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
- SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
+ char *ciphers;
OSStatus err = noErr;
#if CURL_BUILD_MAC
int darwinver_maj = 0, darwinver_min = 0;
@@ -1484,21 +1747,9 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
break;
}
case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol3);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol3);
- break;
case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol2);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol2);
- break;
+ failf(data, "SSL versions not supported");
+ return CURLE_NOT_BUILT_IN;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
@@ -1533,23 +1784,9 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
break;
}
case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kSSLProtocol3,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kSSLProtocol2,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
+ failf(data, "SSL versions not supported");
+ return CURLE_NOT_BUILT_IN;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
@@ -1581,23 +1818,9 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
failf(data, "Your version of the OS does not support TLSv1.3");
return CURLE_SSL_CONNECT_ERROR;
case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kSSLProtocol2,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kSSLProtocol3,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
+ failf(data, "SSL versions not supported");
+ return CURLE_NOT_BUILT_IN;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
@@ -1610,14 +1833,14 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
&kCFTypeArrayCallBacks);
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifdef USE_HTTP2
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_PROXY
- && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
+ && (!isproxy || !conn->bits.tunnel_proxy)
#endif
) {
- CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID));
- infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2));
+ infof(data, "ALPN, offering %s\n", ALPN_H2);
}
#endif
@@ -1788,7 +2011,8 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile);
if(!(is_cert_file || is_cert_data)) {
- failf(data, "SSL: can't load CA certificate file %s", ssl_cafile);
+ failf(data, "SSL: can't load CA certificate file %s",
+ ssl_cafile ? ssl_cafile : "(blob memory)");
return CURLE_SSL_CACERT_BADFILE;
}
}
@@ -1818,121 +2042,16 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
infof(data, "WARNING: disabling hostname validation also disables SNI.\n");
}
- /* Disable cipher suites that ST supports but are not safe. These ciphers
- are unlikely to be used in any case since ST gives other ciphers a much
- higher priority, but it's probably better that we not connect at all than
- to give the user a false sense of security if the server only supports
- insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
- err = SSLGetNumberSupportedCiphers(backend->ssl_ctx, &all_ciphers_count);
- if(err != noErr) {
- failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d",
- err);
- return CURLE_SSL_CIPHER;
- }
- all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- if(!all_ciphers) {
- failf(data, "SSL: Failed to allocate memory for all ciphers");
- return CURLE_OUT_OF_MEMORY;
- }
- allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- if(!allowed_ciphers) {
- Curl_safefree(all_ciphers);
- failf(data, "SSL: Failed to allocate memory for allowed ciphers");
- return CURLE_OUT_OF_MEMORY;
- }
- err = SSLGetSupportedCiphers(backend->ssl_ctx, all_ciphers,
- &all_ciphers_count);
- if(err != noErr) {
- Curl_safefree(all_ciphers);
- Curl_safefree(allowed_ciphers);
- return CURLE_SSL_CIPHER;
+ ciphers = SSL_CONN_CONFIG(cipher_list);
+ if(ciphers) {
+ err = sectransp_set_selected_ciphers(data, backend->ssl_ctx, ciphers);
}
- for(i = 0UL ; i < all_ciphers_count ; i++) {
-#if CURL_BUILD_MAC
- /* There's a known bug in early versions of Mountain Lion where ST's ECC
- ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
- Work around the problem here by disabling those ciphers if we are
- running in an affected version of OS X. */
- if(darwinver_maj == 12 && darwinver_min <= 3 &&
- all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
- continue;
- }
-#endif /* CURL_BUILD_MAC */
- switch(all_ciphers[i]) {
- /* Disable NULL ciphersuites: */
- case SSL_NULL_WITH_NULL_NULL:
- case SSL_RSA_WITH_NULL_MD5:
- case SSL_RSA_WITH_NULL_SHA:
- case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
- case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
- case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
- case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
- case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
- case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
- case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
- case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
- case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
- case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
- case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
- case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
- case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
- case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
- case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
- /* Disable anonymous ciphersuites: */
- case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
- case SSL_DH_anon_WITH_RC4_128_MD5:
- case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_anon_WITH_DES_CBC_SHA:
- case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
- case TLS_DH_anon_WITH_AES_128_CBC_SHA:
- case TLS_DH_anon_WITH_AES_256_CBC_SHA:
- case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
- case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
- case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
- case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
- case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
- case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
- case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
- case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
- case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
- /* Disable weak key ciphersuites: */
- case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
- case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
- case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_RSA_WITH_DES_CBC_SHA:
- case SSL_DH_DSS_WITH_DES_CBC_SHA:
- case SSL_DH_RSA_WITH_DES_CBC_SHA:
- case SSL_DHE_DSS_WITH_DES_CBC_SHA:
- case SSL_DHE_RSA_WITH_DES_CBC_SHA:
- /* Disable IDEA: */
- case SSL_RSA_WITH_IDEA_CBC_SHA:
- case SSL_RSA_WITH_IDEA_CBC_MD5:
- /* Disable RC4: */
- case SSL_RSA_WITH_RC4_128_MD5:
- case SSL_RSA_WITH_RC4_128_SHA:
- case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
- case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
- case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
- case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
- case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
- case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
- case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
- break;
- default: /* enable everything else */
- allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
- break;
- }
+ else {
+ err = sectransp_set_default_ciphers(data, backend->ssl_ctx);
}
- err = SSLSetEnabledCiphers(backend->ssl_ctx, allowed_ciphers,
- allowed_ciphers_count);
- Curl_safefree(all_ciphers);
- Curl_safefree(allowed_ciphers);
if(err != noErr) {
- failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
+ failf(data, "SSL: Unable to set ciphers for SSL/TLS handshake. "
+ "Error code: %d", err);
return CURLE_SSL_CIPHER;
}
@@ -1941,7 +2060,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
specifically doesn't want us doing that: */
if(SSLSetSessionOption != NULL) {
SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
- !data->set.ssl.enable_beast);
+ !SSL_SET_OPTION(enable_beast));
SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart,
data->set.ssl.falsestart); /* false start support */
}
@@ -1953,7 +2072,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
size_t ssl_sessionid_len;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, (void **)&ssl_sessionid,
+ if(!Curl_ssl_getsessionid(data, conn, isproxy, (void **)&ssl_sessionid,
&ssl_sessionid_len, sockindex)) {
/* we got a session id, use it! */
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
@@ -1970,7 +2089,8 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
else {
CURLcode result;
ssl_sessionid =
- aprintf("%s:%d:%d:%s:%ld", ssl_cafile,
+ aprintf("%s:%d:%d:%s:%ld",
+ ssl_cafile ? ssl_cafile : "(blob memory)",
verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
ssl_sessionid_len = strlen(ssl_sessionid);
@@ -1981,7 +2101,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
- result = Curl_ssl_addsessionid(data, conn, ssl_sessionid,
+ result = Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid,
ssl_sessionid_len, sockindex);
Curl_ssl_sessionid_unlock(data);
if(result) {
@@ -2021,21 +2141,21 @@ static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
/* Jump through the separators at the beginning of the certificate. */
sep_start = strstr(in, "-----");
- if(sep_start == NULL)
+ if(!sep_start)
return 0;
cert_start = strstr(sep_start + 1, "-----");
- if(cert_start == NULL)
+ if(!cert_start)
return -1;
cert_start += 5;
/* Find separator after the end of the certificate. */
cert_end = strstr(cert_start, "-----");
- if(cert_end == NULL)
+ if(!cert_end)
return -1;
sep_end = strstr(cert_end + 1, "-----");
- if(sep_end == NULL)
+ if(!sep_end)
return -1;
sep_end += 5;
@@ -2110,7 +2230,7 @@ static int read_cert(const char *file, unsigned char **out, size_t *outlen)
}
static int append_cert_to_array(struct Curl_easy *data,
- unsigned char *buf, size_t buflen,
+ const unsigned char *buf, size_t buflen,
CFMutableArrayRef array)
{
CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
@@ -2148,18 +2268,14 @@ static int append_cert_to_array(struct Curl_easy *data,
return CURLE_OK;
}
-static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
- SSLContextRef ctx)
+static CURLcode verify_cert_buf(struct Curl_easy *data,
+ const unsigned char *certbuf, size_t buflen,
+ SSLContextRef ctx)
{
int n = 0, rc;
long res;
- unsigned char *certbuf, *der;
- size_t buflen, derlen, offset = 0;
-
- if(read_cert(cafile, &certbuf, &buflen) < 0) {
- failf(data, "SSL: failed to read or invalid CA certificate");
- return CURLE_SSL_CACERT_BADFILE;
- }
+ unsigned char *der;
+ size_t derlen, offset = 0;
/*
* Certbuf now contains the contents of the certificate file, which can be
@@ -2172,8 +2288,7 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
*/
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeArrayCallBacks);
- if(array == NULL) {
- free(certbuf);
+ if(!array) {
failf(data, "SSL: out of memory creating CA certificate array");
return CURLE_OUT_OF_MEMORY;
}
@@ -2187,7 +2302,6 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
*/
res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
if(res < 0) {
- free(certbuf);
CFRelease(array);
failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
n, offset);
@@ -2198,7 +2312,6 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
if(res == 0 && offset == 0) {
/* This is not a PEM file, probably a certificate in DER format. */
rc = append_cert_to_array(data, certbuf, buflen, array);
- free(certbuf);
if(rc != CURLE_OK) {
CFRelease(array);
return rc;
@@ -2207,14 +2320,12 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
}
else if(res == 0) {
/* No more certificates in the bundle. */
- free(certbuf);
break;
}
rc = append_cert_to_array(data, der, derlen, array);
free(der);
if(rc != CURLE_OK) {
- free(certbuf);
CFRelease(array);
return rc;
}
@@ -2222,7 +2333,7 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
SecTrustRef trust;
OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
- if(trust == NULL) {
+ if(!trust) {
failf(data, "SSL: error getting certificate chain");
CFRelease(array);
return CURLE_PEER_FAILED_VERIFICATION;
@@ -2271,6 +2382,38 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
}
}
+static CURLcode verify_cert(struct Curl_easy *data, const char *cafile,
+ const struct curl_blob *ca_info_blob,
+ SSLContextRef ctx)
+{
+ int result;
+ unsigned char *certbuf;
+ size_t buflen;
+
+ if(ca_info_blob) {
+ certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
+ if(!certbuf) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+ buflen = ca_info_blob->len;
+ memcpy(certbuf, ca_info_blob->data, ca_info_blob->len);
+ certbuf[ca_info_blob->len]='\0';
+ }
+ else if(cafile) {
+ if(read_cert(cafile, &certbuf, &buflen) < 0) {
+ failf(data, "SSL: failed to read or invalid CA certificate");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else
+ return CURLE_SSL_CACERT_BADFILE;
+
+ result = verify_cert_buf(data, certbuf, buflen, ctx);
+ free(certbuf);
+ return result;
+}
+
+
#ifdef SECTRANSP_PINNEDPUBKEY
static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
SSLContextRef ctx,
@@ -2295,19 +2438,19 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
do {
SecTrustRef trust;
OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
- if(ret != noErr || trust == NULL)
+ if(ret != noErr || !trust)
break;
SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
CFRelease(trust);
- if(keyRef == NULL)
+ if(!keyRef)
break;
#ifdef SECTRANSP_PINNEDPUBKEY_V1
publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
CFRelease(keyRef);
- if(publicKeyBits == NULL)
+ if(!publicKeyBits)
break;
#elif SECTRANSP_PINNEDPUBKEY_V2
@@ -2315,7 +2458,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
&publicKeyBits);
CFRelease(keyRef);
- if(success != errSecSuccess || publicKeyBits == NULL)
+ if(success != errSecSuccess || !publicKeyBits)
break;
#endif /* SECTRANSP_PINNEDPUBKEY_V2 */
@@ -2387,12 +2530,7 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
OSStatus err;
SSLCipherSuite cipher;
SSLProtocol protocol = 0;
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- const char * const hostname = conn->host.name;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
@@ -2411,8 +2549,10 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
/* The below is errSSLServerAuthCompleted; it's not defined in
Leopard's headers */
case -9841:
- if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
- CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
+ if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
+ SSL_CONN_CONFIG(verifypeer)) {
+ CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile),
+ SSL_CONN_CONFIG(ca_info_blob),
backend->ssl_ctx);
if(result)
return result;
@@ -2599,8 +2739,9 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
#if CURL_BUILD_MAC_10_6
/* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
case errSSLClientCertRequested:
- failf(data, "The server has requested a client certificate");
- break;
+ failf(data, "Server requested a client certificate during the "
+ "handshake");
+ return CURLE_SSL_CLIENTCERT;
#endif
#if CURL_BUILD_MAC_10_9
/* Alias for errSSLLast, end of error range */
@@ -2621,9 +2762,10 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
connssl->connecting_state = ssl_connect_3;
#ifdef SECTRANSP_PINNEDPUBKEY
- if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
- CURLcode result = pkp_pin_peer_pubkey(data, backend->ssl_ctx,
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
+ if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+ CURLcode result =
+ pkp_pin_peer_pubkey(data, backend->ssl_ctx,
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
if(result) {
failf(data, "SSL: public key does not match pinned public key!");
return result;
@@ -2637,11 +2779,11 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
switch(protocol) {
case kSSLProtocol2:
infof(data, "SSL 2.0 connection using %s\n",
- SSLCipherNameForNumber(cipher));
+ TLSCipherNameForNumber(cipher));
break;
case kSSLProtocol3:
infof(data, "SSL 3.0 connection using %s\n",
- SSLCipherNameForNumber(cipher));
+ TLSCipherNameForNumber(cipher));
break;
case kTLSProtocol1:
infof(data, "TLS 1.0 connection using %s\n",
@@ -2678,10 +2820,9 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
-#ifdef USE_NGHTTP2
+#ifdef USE_HTTP2
if(chosenProtocol &&
- !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID),
- 0)) {
+ !CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
conn->negnpn = CURL_HTTP_VERSION_2;
}
else
@@ -3255,8 +3396,10 @@ static ssize_t sectransp_recv(struct Curl_easy *data,
/* The below is errSSLPeerAuthCompleted; it's not defined in
Leopard's headers */
case -9841:
- if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
- CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
+ if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
+ SSL_CONN_CONFIG(verifypeer)) {
+ CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile),
+ SSL_CONN_CONFIG(ca_info_blob),
backend->ssl_ctx);
if(result)
return result;
@@ -3283,6 +3426,7 @@ static void *sectransp_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_sectransp = {
{ CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
+ SSLSUPP_CAINFO_BLOB |
#ifdef SECTRANSP_PINNEDPUBKEY
SSLSUPP_PINNEDPUBKEY,
#else
@@ -3301,6 +3445,7 @@ const struct Curl_ssl Curl_ssl_sectransp = {
Curl_none_cert_status_request, /* cert_status_request */
sectransp_connect, /* connect */
sectransp_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
sectransp_get_internals, /* get_internals */
sectransp_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -3309,7 +3454,9 @@ const struct Curl_ssl Curl_ssl_sectransp = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
sectransp_false_start, /* false_start */
- sectransp_sha256sum /* sha256sum */
+ sectransp_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#ifdef __clang__
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index b8ab7494f..65f4f773d 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -135,6 +135,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
(data->verifyhost == needle->verifyhost) &&
(data->verifystatus == needle->verifystatus) &&
blobcmp(data->cert_blob, needle->cert_blob) &&
+ blobcmp(data->ca_info_blob, needle->ca_info_blob) &&
Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
@@ -161,6 +162,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
dest->sessionid = source->sessionid;
CLONE_BLOB(cert_blob);
+ CLONE_BLOB(ca_info_blob);
CLONE_STRING(CApath);
CLONE_STRING(CAfile);
CLONE_STRING(clientcert);
@@ -185,6 +187,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
Curl_safefree(sslc->cipher_list13);
Curl_safefree(sslc->pinned_key);
Curl_safefree(sslc->cert_blob);
+ Curl_safefree(sslc->ca_info_blob);
Curl_safefree(sslc->curves);
}
@@ -315,6 +318,8 @@ Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
if(!result)
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
+ else
+ conn->ssl[sockindex].use = FALSE;
return result;
}
@@ -338,7 +343,9 @@ Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
/* mark this is being ssl requested from here on. */
conn->ssl[sockindex].use = TRUE;
result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
- if(!result && *done)
+ if(result)
+ conn->ssl[sockindex].use = FALSE;
+ else if(*done)
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
return result;
}
@@ -367,6 +374,7 @@ void Curl_ssl_sessionid_unlock(struct Curl_easy *data)
*/
bool Curl_ssl_getsessionid(struct Curl_easy *data,
struct connectdata *conn,
+ const bool isProxy,
void **ssl_sessionid,
size_t *idsize, /* set 0 if unknown */
int sockindex)
@@ -377,7 +385,6 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data,
bool no_match = TRUE;
#ifndef CURL_DISABLE_PROXY
- const bool isProxy = CONNECT_PROXY_SSL();
struct ssl_primary_config * const ssl_config = isProxy ?
&conn->proxy_ssl_config :
&conn->ssl_config;
@@ -389,10 +396,15 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data,
struct ssl_primary_config * const ssl_config = &conn->ssl_config;
const char * const name = conn->host.name;
int port = conn->remote_port;
- (void)sockindex;
#endif
+ (void)sockindex;
*ssl_sessionid = NULL;
+#ifdef CURL_DISABLE_PROXY
+ if(isProxy)
+ return TRUE;
+#endif
+
DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
if(!SSL_SET_OPTION(primary.sessionid))
@@ -480,6 +492,7 @@ void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
*/
CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
struct connectdata *conn,
+ bool isProxy,
void *ssl_sessionid,
size_t idsize,
int sockindex)
@@ -492,19 +505,16 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
int conn_to_port;
long *general_age;
#ifndef CURL_DISABLE_PROXY
- const bool isProxy = CONNECT_PROXY_SSL();
struct ssl_primary_config * const ssl_config = isProxy ?
&conn->proxy_ssl_config :
&conn->ssl_config;
const char *hostname = isProxy ? conn->http_proxy.host.name :
conn->host.name;
#else
- /* proxy support disabled */
- const bool isProxy = FALSE;
struct ssl_primary_config * const ssl_config = &conn->ssl_config;
const char *hostname = conn->host.name;
- (void)sockindex;
#endif
+ (void)sockindex;
DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
clone_host = strdup(hostname);
@@ -576,6 +586,25 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
return CURLE_OK;
}
+void Curl_ssl_associate_conn(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ if(Curl_ssl->associate_connection) {
+ Curl_ssl->associate_connection(data, conn, FIRSTSOCKET);
+ if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted)
+ Curl_ssl->associate_connection(data, conn, SECONDARYSOCKET);
+ }
+}
+
+void Curl_ssl_detach_conn(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ if(Curl_ssl->disassociate_connection) {
+ Curl_ssl->disassociate_connection(data, FIRSTSOCKET);
+ if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted)
+ Curl_ssl->disassociate_connection(data, SECONDARYSOCKET);
+ }
+}
void Curl_ssl_close_all(struct Curl_easy *data)
{
@@ -593,9 +622,6 @@ void Curl_ssl_close_all(struct Curl_easy *data)
Curl_ssl->close_all(data);
}
-#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
- defined(USE_SECTRANSP) || defined(USE_NSS) || \
- defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_BEARSSL)
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks)
{
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
@@ -613,16 +639,6 @@ int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks)
return GETSOCK_BLANK;
}
-#else
-int Curl_ssl_getsock(struct connectdata *conn,
- curl_socket_t *socks)
-{
- (void)conn;
- (void)socks;
- return GETSOCK_BLANK;
-}
-/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */
-#endif
void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
@@ -1170,6 +1186,13 @@ static CURLcode multissl_connect_nonblocking(struct Curl_easy *data,
return Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
}
+static int multissl_getsock(struct connectdata *conn, curl_socket_t *socks)
+{
+ if(multissl_setup(NULL))
+ return 0;
+ return Curl_ssl->getsock(conn, socks);
+}
+
static void *multissl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info)
{
@@ -1201,6 +1224,7 @@ static const struct Curl_ssl Curl_ssl_multi = {
Curl_none_cert_status_request, /* cert_status_request */
multissl_connect, /* connect */
multissl_connect_nonblocking, /* connect_nonblocking */
+ multissl_getsock, /* getsock */
multissl_get_internals, /* get_internals */
multissl_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1209,7 +1233,9 @@ static const struct Curl_ssl Curl_ssl_multi = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- NULL /* sha256sum */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
const struct Curl_ssl *Curl_ssl =
@@ -1227,6 +1253,8 @@ const struct Curl_ssl *Curl_ssl =
&Curl_ssl_mbedtls;
#elif defined(USE_NSS)
&Curl_ssl_nss;
+#elif defined(USE_RUSTLS)
+ &Curl_ssl_rustls;
#elif defined(USE_OPENSSL)
&Curl_ssl_openssl;
#elif defined(USE_SCHANNEL)
@@ -1270,6 +1298,9 @@ static const struct Curl_ssl *available_backends[] = {
#if defined(USE_BEARSSL)
&Curl_ssl_bearssl,
#endif
+#if defined(USE_RUSTLS)
+ &Curl_ssl_rustls,
+#endif
NULL
};
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index 9666682ec..7f93e7aed 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -32,6 +32,7 @@ struct ssl_connect_data;
#define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */
#define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */
#define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */
+#define SSLSUPP_CAINFO_BLOB (1<<6)
struct Curl_ssl {
/*
@@ -62,6 +63,14 @@ struct Curl_ssl {
CURLcode (*connect_nonblocking)(struct Curl_easy *data,
struct connectdata *conn, int sockindex,
bool *done);
+
+ /* If the SSL backend wants to read or write on this connection during a
+ handshake, set socks[0] to the connection's FIRSTSOCKET, and return
+ a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or
+ GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK.
+ Mandatory. */
+ int (*getsock)(struct connectdata *conn, curl_socket_t *socks);
+
void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
void (*close_one)(struct Curl_easy *data, struct connectdata *conn,
int sockindex);
@@ -75,6 +84,11 @@ struct Curl_ssl {
bool (*false_start)(void);
CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
unsigned char *sha256sum, size_t sha256sumlen);
+
+ void (*associate_connection)(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex);
+ void (*disassociate_connection)(struct Curl_easy *data, int sockindex);
};
#ifdef USE_SSL
@@ -108,6 +122,7 @@ bool Curl_ssl_tls13_ciphersuites(void);
#include "mbedtls.h" /* mbedTLS versions */
#include "mesalink.h" /* MesaLink versions */
#include "bearssl.h" /* BearSSL versions */
+#include "rustls.h" /* rustls versions */
#ifndef MAX_PINNED_PUBKEY_SIZE
#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */
@@ -117,9 +132,11 @@ bool Curl_ssl_tls13_ciphersuites(void);
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
#endif
-/* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
+/* see https://www.iana.org/assignments/tls-extensiontype-values/ */
#define ALPN_HTTP_1_1_LENGTH 8
#define ALPN_HTTP_1_1 "http/1.1"
+#define ALPN_H2_LENGTH 2
+#define ALPN_H2 "h2"
/* set of helper macros for the backends to access the correct fields. For the
proxy or for the remote host - to properly support HTTPS proxy */
@@ -139,9 +156,11 @@ bool Curl_ssl_tls13_ciphersuites(void);
(SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name)
#define SSL_HOST_DISPNAME() \
(SSL_IS_PROXY() ? conn->http_proxy.host.dispname : conn->host.dispname)
+#define SSL_HOST_PORT() \
+ (SSL_IS_PROXY() ? conn->port : conn->remote_port)
#define SSL_PINNED_PUB_KEY() (SSL_IS_PROXY() \
? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] \
- : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG])
+ : data->set.str[STRING_SSL_PINNEDPUBLICKEY])
#else
#define SSL_IS_PROXY() FALSE
#define SSL_SET_OPTION(var) data->set.ssl.var
@@ -149,8 +168,9 @@ bool Curl_ssl_tls13_ciphersuites(void);
#define SSL_CONN_CONFIG(var) conn->ssl_config.var
#define SSL_HOST_NAME() conn->host.name
#define SSL_HOST_DISPNAME() conn->host.dispname
+#define SSL_HOST_PORT() conn->remote_port
#define SSL_PINNED_PUB_KEY() \
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY]
#endif
bool Curl_ssl_config_matches(struct ssl_primary_config *data,
@@ -158,6 +178,10 @@ bool Curl_ssl_config_matches(struct ssl_primary_config *data,
bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
struct ssl_primary_config *dest);
void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc);
+/* An implementation of the getsock field of Curl_ssl that relies
+ on the ssl_connect_state enum. Asks for read or write depending
+ on whether conn->state is ssl_connect_2_reading or
+ ssl_connect_2_writing. */
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks);
int Curl_ssl_backend(void);
@@ -222,6 +246,7 @@ void Curl_ssl_sessionid_unlock(struct Curl_easy *data);
*/
bool Curl_ssl_getsessionid(struct Curl_easy *data,
struct connectdata *conn,
+ const bool isproxy,
void **ssl_sessionid,
size_t *idsize, /* set 0 if unknown */
int sockindex);
@@ -232,6 +257,7 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data,
*/
CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
struct connectdata *conn,
+ const bool isProxy,
void *ssl_sessionid,
size_t idsize,
int sockindex);
@@ -262,6 +288,11 @@ bool Curl_ssl_cert_status_request(void);
bool Curl_ssl_false_start(void);
+void Curl_ssl_associate_conn(struct Curl_easy *data,
+ struct connectdata *conn);
+void Curl_ssl_detach_conn(struct Curl_easy *data,
+ struct connectdata *conn);
+
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
#else /* if not USE_SSL */
@@ -288,6 +319,8 @@ bool Curl_ssl_false_start(void);
#define Curl_ssl_cert_status_request() FALSE
#define Curl_ssl_false_start() FALSE
#define Curl_ssl_tls13_ciphersuites() FALSE
+#define Curl_ssl_associate_conn(a,b) Curl_nop_stmt
+#define Curl_ssl_detach_conn(a,b) Curl_nop_stmt
#endif
#endif /* HEADER_CURL_VTLS_H */
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.c b/Utilities/cmcurl/lib/vtls/wolfssl.c
index e1fa45926..60e27e366 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.c
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.c
@@ -47,16 +47,6 @@
#endif
#endif
-/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in
- options.h, but is only seen in >= 3.6.6 since that's when they started
- disabling SSLv3 by default. */
-#ifndef WOLFSSL_ALLOW_SSLV3
-#if (LIBWOLFSSL_VERSION_HEX < 0x03006006) || \
- defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
-#define WOLFSSL_ALLOW_SSLV3
-#endif
-#endif
-
#include <limits.h>
#include "urldata.h"
@@ -285,18 +275,6 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
failf(data, "wolfSSL: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
#endif
- case CURL_SSLVERSION_SSLv3:
-#ifdef WOLFSSL_ALLOW_SSLV3
- req_method = SSLv3_client_method();
- use_sni(FALSE);
-#else
- failf(data, "wolfSSL does not support SSLv3");
- return CURLE_NOT_BUILT_IN;
-#endif
- break;
- case CURL_SSLVERSION_SSLv2:
- failf(data, "wolfSSL does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
@@ -418,12 +396,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#ifdef ENABLE_IPV6
struct in6_addr addr6;
#endif
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- const char * const hostname = conn->host.name;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
size_t hostname_len = strlen(hostname);
if((hostname_len < USHRT_MAX) &&
(0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
@@ -474,10 +447,10 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
/* wolfSSL's ALPN protocol name list format is a comma separated string of
protocols in descending order of preference, eg: "h2,http/1.1" */
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
- strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ",");
- infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+#ifdef USE_HTTP2
+ if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
+ strcpy(protocols + strlen(protocols), ALPN_H2 ",");
+ infof(data, "ALPN, offering %s\n", ALPN_H2);
}
#endif
@@ -516,7 +489,9 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
void *ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(data, conn,
+ SSL_IS_PROXY() ? TRUE : FALSE,
+ &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
@@ -550,20 +525,9 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
int ret = -1;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- const char * const dispname = SSL_IS_PROXY() ?
- conn->http_proxy.host.dispname : conn->host.dispname;
- const char * const pinnedpubkey = SSL_IS_PROXY() ?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-#else
- const char * const hostname = conn->host.name;
- const char * const dispname = conn->host.dispname;
- const char * const pinnedpubkey =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-#endif
+ const char * const hostname = SSL_HOST_NAME();
+ const char * const dispname = SSL_HOST_DISPNAME();
+ const char * const pinnedpubkey = SSL_PINNED_PUB_KEY();
conn->recv[sockindex] = wolfssl_recv;
conn->send[sockindex] = wolfssl_send;
@@ -723,11 +687,10 @@ 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;
-#ifdef USE_NGHTTP2
- else if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
- protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
- !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID,
- NGHTTP2_PROTO_VERSION_ID_LEN))
+#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;
#endif
else
@@ -770,32 +733,33 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
- SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
-
- our_ssl_sessionid = SSL_get_session(backend->handle);
-
- Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL,
- sockindex));
- if(incache) {
- if(old_ssl_sessionid != our_ssl_sessionid) {
- infof(data, "old SSL session ID is stale, removing\n");
- Curl_ssl_delsessionid(data, old_ssl_sessionid);
- incache = FALSE;
+ SSL_SESSION *our_ssl_sessionid = SSL_get_session(backend->handle);
+ bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
+
+ if(our_ssl_sessionid) {
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn, isproxy,
+ &old_ssl_sessionid, NULL, sockindex));
+ if(incache) {
+ if(old_ssl_sessionid != our_ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
+ incache = FALSE;
+ }
}
- }
- if(!incache) {
- result = Curl_ssl_addsessionid(data, conn, our_ssl_sessionid,
- 0 /* unknown size */, sockindex);
- if(result) {
- Curl_ssl_sessionid_unlock(data);
- failf(data, "failed to store ssl session");
- return result;
+ if(!incache) {
+ result = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid,
+ 0, sockindex);
+ if(result) {
+ Curl_ssl_sessionid_unlock(data);
+ failf(data, "failed to store ssl session");
+ return result;
+ }
}
+ Curl_ssl_sessionid_unlock(data);
}
- Curl_ssl_sessionid_unlock(data);
}
connssl->connecting_state = ssl_connect_done;
@@ -817,7 +781,7 @@ static ssize_t wolfssl_send(struct Curl_easy *data,
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
int rc = SSL_write(backend->handle, mem, memlen);
- if(rc < 0) {
+ if(rc <= 0) {
int err = SSL_get_error(backend->handle, rc);
switch(err) {
@@ -1152,6 +1116,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
Curl_none_cert_status_request, /* cert_status_request */
wolfssl_connect, /* connect */
wolfssl_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
wolfssl_get_internals, /* get_internals */
wolfssl_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1160,7 +1125,9 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- wolfssl_sha256sum /* sha256sum */
+ wolfssl_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#endif
diff --git a/Utilities/cmcurl/lib/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c
index f29aa05b8..281c97248 100644
--- a/Utilities/cmcurl/lib/x509asn1.c
+++ b/Utilities/cmcurl/lib/x509asn1.c
@@ -1145,10 +1145,8 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
int matched = -1;
size_t addrlen = (size_t) -1;
ssize_t len;
- const char *const hostname = SSL_IS_PROXY()?
- conn->http_proxy.host.name : conn->host.name;
- const char *const dispname = SSL_IS_PROXY()?
- conn->http_proxy.host.dispname : conn->host.dispname;
+ const char * const hostname = SSL_HOST_NAME();
+ const char * const dispname = SSL_HOST_DISPNAME();
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
diff --git a/Utilities/cmexpat/CMakeLists.txt b/Utilities/cmexpat/CMakeLists.txt
index b8dc4e8cc..ce7292728 100644
--- a/Utilities/cmexpat/CMakeLists.txt
+++ b/Utilities/cmexpat/CMakeLists.txt
@@ -1,12 +1,14 @@
# Disable warnings to avoid changing 3rd party code.
IF(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
ENDIF()
include(ConfigureChecks.cmake)
+configure_file(expat_config.h.cmake expat_config.h @ONLY)
+
if(NOT WIN32)
add_definitions(-DXML_DEV_URANDOM)
endif()
diff --git a/Utilities/cmexpat/README.md b/Utilities/cmexpat/README.md
index 428a11ab2..251dc8a19 100644
--- a/Utilities/cmexpat/README.md
+++ b/Utilities/cmexpat/README.md
@@ -1,12 +1,14 @@
-[![Travis CI Build Status](https://travis-ci.org/libexpat/libexpat.svg?branch=master)](https://travis-ci.org/libexpat/libexpat)
+[![Run Linux Travis CI tasks](https://github.com/libexpat/libexpat/actions/workflows/linux.yml/badge.svg)](https://github.com/libexpat/libexpat/actions/workflows/linux.yml)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/libexpat/libexpat?svg=true)](https://ci.appveyor.com/project/libexpat/libexpat)
[![Packaging status](https://repology.org/badge/tiny-repos/expat.svg)](https://repology.org/metapackage/expat/versions)
+[![Downloads SourceForge](https://img.shields.io/sourceforge/dt/expat?label=Downloads%20SourceForge)](https://sourceforge.net/projects/expat/files/)
+[![Downloads GitHub](https://img.shields.io/github/downloads/libexpat/libexpat/total?label=Downloads%20GitHub)](https://github.com/libexpat/libexpat/releases)
-# Expat, Release 2.2.10
+# Expat, Release 2.4.1
This is Expat, a C library for parsing XML, started by
-[James Clark](https://en.wikipedia.org/wiki/James_Clark_(programmer)) in 1997.
+[James Clark](https://en.wikipedia.org/wiki/James_Clark_%28programmer%29) in 1997.
Expat is a stream-oriented XML parser. This means that you register
handlers with the parser before starting the parse. These handlers
are called when the parser discovers the associated structures in the
@@ -14,13 +16,14 @@ document being parsed. A start tag is an example of the kind of
structures for which you may register handlers.
Expat supports the following compilers:
+
- GNU GCC >=4.5
- LLVM Clang >=3.5
-- Microsoft Visual Studio >=9.0/2008
+- Microsoft Visual Studio >=15.0/2017 (rolling `${today} minus 5 years`)
Windows users can use the
-[`expat_win32` package](https://sourceforge.net/projects/expat/files/expat_win32/),
-which includes both precompiled libraries and executables, and source code for
+[`expat-win32bin-*.*.*.{exe,zip}` download](https://github.com/libexpat/libexpat/releases),
+which includes both pre-compiled libraries and executables, and source code for
developers.
Expat is [free software](https://www.gnu.org/philosophy/free-sw.en.html).
@@ -30,6 +33,67 @@ contained in the file
distributed with this package.
This license is the same as the MIT/X Consortium license.
+
+## Using libexpat in your CMake-Based Project
+
+There are two ways of using libexpat with CMake:
+
+### a) Module Mode
+
+This approach leverages CMake's own [module `FindEXPAT`](https://cmake.org/cmake/help/latest/module/FindEXPAT.html).
+
+Notice the *uppercase* `EXPAT` in the following example:
+
+```cmake
+cmake_minimum_required(VERSION 3.0) # or 3.10, see below
+
+project(hello VERSION 1.0.0)
+
+find_package(EXPAT 2.2.8 MODULE REQUIRED)
+
+add_executable(hello
+ hello.c
+)
+
+# a) for CMake >=3.10 (see CMake's FindEXPAT docs)
+target_link_libraries(hello PUBLIC EXPAT::EXPAT)
+
+# b) for CMake >=3.0
+target_include_directories(hello PRIVATE ${EXPAT_INCLUDE_DIRS})
+target_link_libraries(hello PUBLIC ${EXPAT_LIBRARIES})
+```
+
+### b) Config Mode
+
+This approach requires files from…
+
+- libexpat >=2.2.8 where packaging uses the CMake build system
+or
+- libexpat >=2.3.0 where packaging uses the GNU Autotools build system
+ on Linux
+or
+- libexpat >=2.4.0 where packaging uses the GNU Autotools build system
+ on macOS or MinGW.
+
+Notice the *lowercase* `expat` in the following example:
+
+```cmake
+cmake_minimum_required(VERSION 3.0)
+
+project(hello VERSION 1.0.0)
+
+find_package(expat 2.2.8 CONFIG REQUIRED char dtd ns)
+
+add_executable(hello
+ hello.c
+)
+
+target_link_libraries(hello PUBLIC expat::expat)
+```
+
+
+## Building from a Git Clone
+
If you are building Expat from a check-out from the
[Git repository](https://github.com/libexpat/libexpat/),
you need to run a script that generates the configure script using the
@@ -43,6 +107,11 @@ autoconf 2.58 or newer. Run the script like this:
Once this has been done, follow the same instructions as for building
from a source distribution.
+
+## Building from a Source Distribution
+
+### a) Building with the configure script (i.e. GNU Autotools)
+
To build Expat from a source distribution, you first run the
configuration shell script in the top level distribution directory:
@@ -132,8 +201,14 @@ A reference manual is available in the file `doc/reference.html` in this
distribution.
-The CMake build system is still *experimental* and will replace the primary
+### b) Building with CMake
+
+The CMake build system is still *experimental* and may replace the primary
build system based on GNU Autotools at some point when it is ready.
+
+
+#### Available Options
+
For an idea of the available (non-advanced) options for building with CMake:
```console
diff --git a/Utilities/cmexpat/lib/ascii.h b/Utilities/cmexpat/lib/ascii.h
index c3587e573..1f594d2e5 100644
--- a/Utilities/cmexpat/lib/ascii.h
+++ b/Utilities/cmexpat/lib/ascii.h
@@ -6,8 +6,11 @@
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
- Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 1999-2000 Thai Open Source Software Center Ltd
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2007 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/asciitab.h b/Utilities/cmexpat/lib/asciitab.h
index 63b1d1b44..af766fb24 100644
--- a/Utilities/cmexpat/lib/asciitab.h
+++ b/Utilities/cmexpat/lib/asciitab.h
@@ -7,7 +7,9 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/expat.h b/Utilities/cmexpat/lib/expat.h
index cb828db15..b7d6d3548 100644
--- a/Utilities/cmexpat/lib/expat.h
+++ b/Utilities/cmexpat/lib/expat.h
@@ -7,7 +7,14 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2000-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
+ Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016 Cristian Rodríguez <crrodriguez@opensuse.org>
+ Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
+ Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -115,7 +122,11 @@ enum XML_Error {
XML_ERROR_RESERVED_PREFIX_XMLNS,
XML_ERROR_RESERVED_NAMESPACE_URI,
/* Added in 2.2.1. */
- XML_ERROR_INVALID_ARGUMENT
+ XML_ERROR_INVALID_ARGUMENT,
+ /* Added in 2.3.0. */
+ XML_ERROR_NO_BUFFER,
+ /* Added in 2.4.0. */
+ XML_ERROR_AMPLIFICATION_LIMIT_BREACH
};
enum XML_Content_Type {
@@ -513,7 +524,7 @@ typedef struct {
Otherwise it must return XML_STATUS_ERROR.
If info does not describe a suitable encoding, then the parser will
- return an XML_UNKNOWN_ENCODING error.
+ return an XML_ERROR_UNKNOWN_ENCODING error.
*/
typedef int(XMLCALL *XML_UnknownEncodingHandler)(void *encodingHandlerData,
const XML_Char *name,
@@ -997,7 +1008,10 @@ enum XML_FeatureEnum {
XML_FEATURE_SIZEOF_XML_LCHAR,
XML_FEATURE_NS,
XML_FEATURE_LARGE_SIZE,
- XML_FEATURE_ATTR_INFO
+ XML_FEATURE_ATTR_INFO,
+ /* Added in Expat 2.4.0. */
+ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
+ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT
/* Additional features must be added to the end of this enum. */
};
@@ -1010,12 +1024,24 @@ typedef struct {
XMLPARSEAPI(const XML_Feature *)
XML_GetFeatureList(void);
+#ifdef XML_DTD
+/* Added in Expat 2.4.0. */
+XMLPARSEAPI(XML_Bool)
+XML_SetBillionLaughsAttackProtectionMaximumAmplification(
+ XML_Parser parser, float maximumAmplificationFactor);
+
+/* Added in Expat 2.4.0. */
+XMLPARSEAPI(XML_Bool)
+XML_SetBillionLaughsAttackProtectionActivationThreshold(
+ XML_Parser parser, unsigned long long activationThresholdBytes);
+#endif
+
/* Expat follows the semantic versioning convention.
See http://semver.org.
*/
#define XML_MAJOR_VERSION 2
-#define XML_MINOR_VERSION 2
-#define XML_MICRO_VERSION 10
+#define XML_MINOR_VERSION 4
+#define XML_MICRO_VERSION 1
#ifdef __cplusplus
}
diff --git a/Utilities/cmexpat/lib/expat_external.h b/Utilities/cmexpat/lib/expat_external.h
index ec4783a9b..e03cb445c 100644
--- a/Utilities/cmexpat/lib/expat_external.h
+++ b/Utilities/cmexpat/lib/expat_external.h
@@ -7,7 +7,14 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2000-2004 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
+ Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2016 Cristian Rodríguez <crrodriguez@opensuse.org>
+ Copyright (c) 2016-2019 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
+ Copyright (c) 2018 Yury Gribov <tetra2005@gmail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/iasciitab.h b/Utilities/cmexpat/lib/iasciitab.h
index ea97cfcf6..5d8646f2a 100644
--- a/Utilities/cmexpat/lib/iasciitab.h
+++ b/Utilities/cmexpat/lib/iasciitab.h
@@ -7,7 +7,9 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/internal.h b/Utilities/cmexpat/lib/internal.h
index 60913dab7..444eba0fb 100644
--- a/Utilities/cmexpat/lib/internal.h
+++ b/Utilities/cmexpat/lib/internal.h
@@ -25,8 +25,12 @@
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
- Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
+ Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2018 Yury Gribov <tetra2005@gmail.com>
+ Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -101,22 +105,58 @@
# endif
#endif
+#include <limits.h> // ULONG_MAX
+
+#if defined(_WIN32) && ! defined(__USE_MINGW_ANSI_STDIO)
+# define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
+# if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW
+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
+# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "I64u"
+# else
+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
+# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
+# endif
+#else
+# define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
+# if ! defined(ULONG_MAX)
+# error Compiler did not define ULONG_MAX for us
+# elif ULONG_MAX == 18446744073709551615u // 2^64-1
+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld"
+# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu"
+# else
+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
+# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
+# endif
+#endif
+
#ifndef UNUSED_P
# define UNUSED_P(p) (void)p
#endif
+/* NOTE BEGIN If you ever patch these defaults to greater values
+ for non-attack XML payload in your environment,
+ please file a bug report with libexpat. Thank you!
+*/
+#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT \
+ 100.0f
+#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \
+ 8388608 // 8 MiB, 2^23
+/* NOTE END */
+
+#include "expat.h" // so we can use type XML_Parser below
+
#ifdef __cplusplus
extern "C" {
#endif
-#ifdef XML_ENABLE_VISIBILITY
-# if XML_ENABLE_VISIBILITY
-__attribute__((visibility("default")))
-# endif
+void _INTERNAL_trim_to_complete_utf8_characters(const char *from,
+ const char **fromLimRef);
+
+#if defined(XML_DTD)
+unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser);
+unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser);
+const char *unsignedCharToPrintable(unsigned char c);
#endif
-void
-_INTERNAL_trim_to_complete_utf8_characters(const char *from,
- const char **fromLimRef);
#ifdef __cplusplus
}
diff --git a/Utilities/cmexpat/lib/latin1tab.h b/Utilities/cmexpat/lib/latin1tab.h
index 6f9160413..b681d278a 100644
--- a/Utilities/cmexpat/lib/latin1tab.h
+++ b/Utilities/cmexpat/lib/latin1tab.h
@@ -7,7 +7,9 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/nametab.h b/Utilities/cmexpat/lib/nametab.h
index 3681df348..63485446b 100644
--- a/Utilities/cmexpat/lib/nametab.h
+++ b/Utilities/cmexpat/lib/nametab.h
@@ -6,8 +6,8 @@
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
- Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/siphash.h b/Utilities/cmexpat/lib/siphash.h
index a335ec06e..952f1c88b 100644
--- a/Utilities/cmexpat/lib/siphash.h
+++ b/Utilities/cmexpat/lib/siphash.h
@@ -11,6 +11,9 @@
* --------------------------------------------------------------------------
* HISTORY:
*
+ * 2020-10-03 (Sebastian Pipping)
+ * - Drop support for Visual Studio 9.0/2008 and earlier
+ *
* 2019-08-03 (Sebastian Pipping)
* - Mark part of sip24_valid as to be excluded from clang-format
* - Re-format code using clang-format 9
diff --git a/Utilities/cmexpat/lib/utf8tab.h b/Utilities/cmexpat/lib/utf8tab.h
index a22986acb..88efcf91c 100644
--- a/Utilities/cmexpat/lib/utf8tab.h
+++ b/Utilities/cmexpat/lib/utf8tab.h
@@ -7,7 +7,9 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/winconfig.h b/Utilities/cmexpat/lib/winconfig.h
index fe23035d0..a689db69b 100644
--- a/Utilities/cmexpat/lib/winconfig.h
+++ b/Utilities/cmexpat/lib/winconfig.h
@@ -6,8 +6,10 @@
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
- Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
+ Copyright (c) 2005 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -40,19 +42,6 @@
#include <memory.h>
#include <string.h>
-#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */
-# include <expat_config.h>
-#else /* !defined(HAVE_EXPAT_CONFIG_H) */
-
-# define XML_NS 1
-# define XML_DTD 1
-# define XML_CONTEXT_BYTES 1024
-
-/* we will assume all Windows platforms are little endian */
-# define BYTEORDER 1234
-
-#endif /* !defined(HAVE_EXPAT_CONFIG_H) */
-
#if defined(_MSC_VER)
# pragma warning(push,1)
# pragma warning(disable:4311) /* pointer truncation */
diff --git a/Utilities/cmexpat/lib/xmlparse.c b/Utilities/cmexpat/lib/xmlparse.c
index dfc316ca3..5ba56eaea 100644
--- a/Utilities/cmexpat/lib/xmlparse.c
+++ b/Utilities/cmexpat/lib/xmlparse.c
@@ -1,4 +1,4 @@
-/* 5cd169f2942b85c05e0b1b96f9990f91ac3d07e470ad7ce906ac8590c8ed4f35 (2.2.10+)
+/* 8539b9040d9d901366a62560a064af7cb99811335784b363abc039c5b0ebc416 (2.4.1+)
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
@@ -7,7 +7,31 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2000-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
+ Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2005-2009 Steven Solie <ssolie@users.sourceforge.net>
+ Copyright (c) 2016 Eric Rahm <erahm@mozilla.com>
+ Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016 Gaurav <g.gupta@samsung.com>
+ Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
+ Copyright (c) 2016 Gustavo Grieco <gustavo.grieco@imag.fr>
+ Copyright (c) 2016 Pascal Cuoq <cuoq@trust-in-soft.com>
+ Copyright (c) 2016 Ed Schouten <ed@nuxi.nl>
+ Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk>
+ Copyright (c) 2017 Václav Slavík <vaclav@slavik.io>
+ Copyright (c) 2017 Viktor Szakats <commit@vsz.me>
+ Copyright (c) 2017 Chanho Park <chanho61.park@samsung.com>
+ Copyright (c) 2017 Rolf Eike Beer <eike@sf-mail.de>
+ Copyright (c) 2017 Hans Wennborg <hans@chromium.org>
+ Copyright (c) 2018 Anton Maklakov <antmak.pub@gmail.com>
+ Copyright (c) 2018 Benjamin Peterson <benjamin@python.org>
+ Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it>
+ Copyright (c) 2018 Mariusz Zaborski <oshogbo@vexillium.org>
+ Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
+ Copyright (c) 2019-2020 Ben Wagner <bungeman@chromium.org>
+ Copyright (c) 2019 Vadim Zeitlin <vadim@zeitlins.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -47,17 +71,8 @@
#include <limits.h> /* UINT_MAX */
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* getenv, rand_s */
-
-#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1600)
-/* vs2008/9.0 and earlier lack stdint.h; _MSC_VER 1600 is vs2010/10.0 */
-# if defined(_WIN64)
-typedef unsigned __int64 uintptr_t;
-# else
-typedef unsigned __int32 uintptr_t;
-# endif
-#else
-# include <stdint.h> /* uintptr_t */
-#endif
+#include <stdint.h> /* uintptr_t */
+#include <math.h> /* isnan */
#ifdef _WIN32
# define getpid GetCurrentProcessId
@@ -73,9 +88,9 @@ typedef unsigned __int32 uintptr_t;
#ifdef _WIN32
# include "winconfig.h"
-#elif defined(HAVE_EXPAT_CONFIG_H)
-# include <expat_config.h>
-#endif /* ndef _WIN32 */
+#endif
+
+#include <expat_config.h>
#include "ascii.h"
#include "expat.h"
@@ -382,6 +397,31 @@ typedef struct open_internal_entity {
XML_Bool betweenDecl; /* WFC: PE Between Declarations */
} OPEN_INTERNAL_ENTITY;
+enum XML_Account {
+ XML_ACCOUNT_DIRECT, /* bytes directly passed to the Expat parser */
+ XML_ACCOUNT_ENTITY_EXPANSION, /* intermediate bytes produced during entity
+ expansion */
+ XML_ACCOUNT_NONE /* i.e. do not account, was accounted already */
+};
+
+#ifdef XML_DTD
+typedef unsigned long long XmlBigCount;
+typedef struct accounting {
+ XmlBigCount countBytesDirect;
+ XmlBigCount countBytesIndirect;
+ int debugLevel;
+ float maximumAmplificationFactor; // >=1.0
+ unsigned long long activationThresholdBytes;
+} ACCOUNTING;
+
+typedef struct entity_stats {
+ unsigned int countEverOpened;
+ unsigned int currentDepth;
+ unsigned int maximumDepthSeen;
+ int debugLevel;
+} ENTITY_STATS;
+#endif /* XML_DTD */
+
typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
const char *end, const char **endPtr);
@@ -412,16 +452,18 @@ static enum XML_Error initializeEncoding(XML_Parser parser);
static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
const char *s, const char *end, int tok,
const char *next, const char **nextPtr,
- XML_Bool haveMore, XML_Bool allowClosingDoctype);
+ XML_Bool haveMore, XML_Bool allowClosingDoctype,
+ enum XML_Account account);
static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
XML_Bool betweenDecl);
static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
const ENCODING *enc, const char *start,
const char *end, const char **endPtr,
- XML_Bool haveMore);
+ XML_Bool haveMore, enum XML_Account account);
static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *,
const char **startPtr, const char *end,
- const char **nextPtr, XML_Bool haveMore);
+ const char **nextPtr, XML_Bool haveMore,
+ enum XML_Account account);
#ifdef XML_DTD
static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *,
const char **startPtr, const char *end,
@@ -431,7 +473,8 @@ static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *,
static void freeBindings(XML_Parser parser, BINDING *bindings);
static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *,
const char *s, TAG_NAME *tagNamePtr,
- BINDING **bindingsPtr);
+ BINDING **bindingsPtr,
+ enum XML_Account account);
static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
const ATTRIBUTE_ID *attId, const XML_Char *uri,
BINDING **bindingsPtr);
@@ -440,15 +483,18 @@ static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
XML_Parser parser);
static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *,
XML_Bool isCdata, const char *,
- const char *, STRING_POOL *);
+ const char *, STRING_POOL *,
+ enum XML_Account account);
static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *,
XML_Bool isCdata, const char *,
- const char *, STRING_POOL *);
+ const char *, STRING_POOL *,
+ enum XML_Account account);
static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end);
static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
- const char *start, const char *end);
+ const char *start, const char *end,
+ enum XML_Account account);
static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end);
static int reportComment(XML_Parser parser, const ENCODING *enc,
@@ -512,6 +558,34 @@ static XML_Parser parserCreate(const XML_Char *encodingName,
static void parserInit(XML_Parser parser, const XML_Char *encodingName);
+#ifdef XML_DTD
+static float accountingGetCurrentAmplification(XML_Parser rootParser);
+static void accountingReportStats(XML_Parser originParser, const char *epilog);
+static void accountingOnAbort(XML_Parser originParser);
+static void accountingReportDiff(XML_Parser rootParser,
+ unsigned int levelsAwayFromRootParser,
+ const char *before, const char *after,
+ ptrdiff_t bytesMore, int source_line,
+ enum XML_Account account);
+static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok,
+ const char *before, const char *after,
+ int source_line,
+ enum XML_Account account);
+
+static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity,
+ const char *action, int sourceLine);
+static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity,
+ int sourceLine);
+static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity,
+ int sourceLine);
+
+static XML_Parser getRootParserOf(XML_Parser parser,
+ unsigned int *outLevelDiff);
+#endif /* XML_DTD */
+
+static unsigned long getDebugLevel(const char *variableName,
+ unsigned long defaultDebugLevel);
+
#define poolStart(pool) ((pool)->start)
#define poolEnd(pool) ((pool)->ptr)
#define poolLength(pool) ((pool)->ptr - (pool)->start)
@@ -625,6 +699,10 @@ struct XML_ParserStruct {
enum XML_ParamEntityParsing m_paramEntityParsing;
#endif
unsigned long m_hash_secret_salt;
+#ifdef XML_DTD
+ ACCOUNTING m_accounting;
+ ENTITY_STATS m_entity_stats;
+#endif
};
#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
@@ -809,9 +887,8 @@ gather_time_entropy(void) {
static unsigned long
ENTROPY_DEBUG(const char *label, unsigned long entropy) {
- const char *const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
- if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
- fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
+ if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) {
+ fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
(int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
}
return entropy;
@@ -1073,6 +1150,18 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
#endif
parser->m_hash_secret_salt = 0;
+
+#ifdef XML_DTD
+ memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
+ parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
+ parser->m_accounting.maximumAmplificationFactor
+ = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT;
+ parser->m_accounting.activationThresholdBytes
+ = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT;
+
+ memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS));
+ parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u);
+#endif
}
/* moves list of bindings to m_freeBindingList */
@@ -1893,6 +1982,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
parser->m_errorCode = XML_ERROR_FINISHED;
return XML_STATUS_ERROR;
case XML_INITIALIZED:
+ /* Has someone called XML_GetBuffer successfully before? */
+ if (! parser->m_bufferPtr) {
+ parser->m_errorCode = XML_ERROR_NO_BUFFER;
+ return XML_STATUS_ERROR;
+ }
+
if (parser->m_parentParser == NULL && ! startParsing(parser)) {
parser->m_errorCode = XML_ERROR_NO_MEMORY;
return XML_STATUS_ERROR;
@@ -2337,6 +2432,14 @@ XML_ErrorString(enum XML_Error code) {
/* Added in 2.2.5. */
case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
return XML_L("invalid argument");
+ /* Added in 2.3.0. */
+ case XML_ERROR_NO_BUFFER:
+ return XML_L(
+ "a successful prior call to function XML_GetBuffer is required");
+ /* Added in 2.4.0. */
+ case XML_ERROR_AMPLIFICATION_LIMIT_BREACH:
+ return XML_L(
+ "limit on input amplification factor (from DTD and entities) breached");
}
return NULL;
}
@@ -2373,41 +2476,75 @@ XML_ExpatVersionInfo(void) {
const XML_Feature *XMLCALL
XML_GetFeatureList(void) {
- static const XML_Feature features[]
- = {{XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
- sizeof(XML_Char)},
- {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
- sizeof(XML_LChar)},
+ static const XML_Feature features[] = {
+ {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
+ sizeof(XML_Char)},
+ {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
+ sizeof(XML_LChar)},
#ifdef XML_UNICODE
- {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
+ {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
#endif
#ifdef XML_UNICODE_WCHAR_T
- {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
+ {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
#endif
#ifdef XML_DTD
- {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
+ {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
#endif
#ifdef XML_CONTEXT_BYTES
- {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
- XML_CONTEXT_BYTES},
+ {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
+ XML_CONTEXT_BYTES},
#endif
#ifdef XML_MIN_SIZE
- {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
+ {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
#endif
#ifdef XML_NS
- {XML_FEATURE_NS, XML_L("XML_NS"), 0},
+ {XML_FEATURE_NS, XML_L("XML_NS"), 0},
#endif
#ifdef XML_LARGE_SIZE
- {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
+ {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
#endif
#ifdef XML_ATTR_INFO
- {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
+ {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
#endif
- {XML_FEATURE_END, NULL, 0}};
+#ifdef XML_DTD
+ /* Added in Expat 2.4.0. */
+ {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
+ XML_L("XML_BLAP_MAX_AMP"),
+ (long int)
+ EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT},
+ {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
+ XML_L("XML_BLAP_ACT_THRES"),
+ EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT},
+#endif
+ {XML_FEATURE_END, NULL, 0}};
return features;
}
+#ifdef XML_DTD
+XML_Bool XMLCALL
+XML_SetBillionLaughsAttackProtectionMaximumAmplification(
+ XML_Parser parser, float maximumAmplificationFactor) {
+ if ((parser == NULL) || (parser->m_parentParser != NULL)
+ || isnan(maximumAmplificationFactor)
+ || (maximumAmplificationFactor < 1.0f)) {
+ return XML_FALSE;
+ }
+ parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor;
+ return XML_TRUE;
+}
+
+XML_Bool XMLCALL
+XML_SetBillionLaughsAttackProtectionActivationThreshold(
+ XML_Parser parser, unsigned long long activationThresholdBytes) {
+ if ((parser == NULL) || (parser->m_parentParser != NULL)) {
+ return XML_FALSE;
+ }
+ parser->m_accounting.activationThresholdBytes = activationThresholdBytes;
+ return XML_TRUE;
+}
+#endif /* XML_DTD */
+
/* Initially tag->rawName always points into the parse buffer;
for those TAG instances opened while the current parse buffer was
processed, and not yet closed, we need to store tag->rawName in a more
@@ -2460,9 +2597,9 @@ storeRawNames(XML_Parser parser) {
static enum XML_Error PTRCALL
contentProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
- enum XML_Error result
- = doContent(parser, 0, parser->m_encoding, start, end, endPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer);
+ enum XML_Error result = doContent(
+ parser, 0, parser->m_encoding, start, end, endPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
if (result == XML_ERROR_NONE) {
if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
@@ -2487,6 +2624,14 @@ externalEntityInitProcessor2(XML_Parser parser, const char *start,
int tok = XmlContentTok(parser->m_encoding, start, end, &next);
switch (tok) {
case XML_TOK_BOM:
+#ifdef XML_DTD
+ if (! accountingDiffTolerated(parser, tok, start, next, __LINE__,
+ XML_ACCOUNT_DIRECT)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+#endif /* XML_DTD */
+
/* If we are at the end of the buffer, this would cause the next stage,
i.e. externalEntityInitProcessor3, to pass control directly to
doContent (by detecting XML_TOK_NONE) without processing any xml text
@@ -2524,6 +2669,10 @@ externalEntityInitProcessor3(XML_Parser parser, const char *start,
const char *next = start; /* XmlContentTok doesn't always set the last arg */
parser->m_eventPtr = start;
tok = XmlContentTok(parser->m_encoding, start, end, &next);
+ /* Note: These bytes are accounted later in:
+ - processXmlDecl
+ - externalEntityContentProcessor
+ */
parser->m_eventEndPtr = next;
switch (tok) {
@@ -2565,7 +2714,8 @@ externalEntityContentProcessor(XML_Parser parser, const char *start,
const char *end, const char **endPtr) {
enum XML_Error result
= doContent(parser, 1, parser->m_encoding, start, end, endPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer);
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer,
+ XML_ACCOUNT_ENTITY_EXPANSION);
if (result == XML_ERROR_NONE) {
if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
@@ -2576,7 +2726,7 @@ externalEntityContentProcessor(XML_Parser parser, const char *start,
static enum XML_Error
doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
const char *s, const char *end, const char **nextPtr,
- XML_Bool haveMore) {
+ XML_Bool haveMore, enum XML_Account account) {
/* save one level of indirection */
DTD *const dtd = parser->m_dtd;
@@ -2594,6 +2744,17 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
for (;;) {
const char *next = s; /* XmlContentTok doesn't always set the last arg */
int tok = XmlContentTok(enc, s, end, &next);
+#ifdef XML_DTD
+ const char *accountAfter
+ = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR))
+ ? (haveMore ? s /* i.e. 0 bytes */ : end)
+ : next;
+ if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__,
+ account)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+#endif
*eventEndPP = next;
switch (tok) {
case XML_TOK_TRAILING_CR:
@@ -2649,6 +2810,14 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
XML_Char ch = (XML_Char)XmlPredefinedEntityName(
enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
if (ch) {
+#ifdef XML_DTD
+ /* NOTE: We are replacing 4-6 characters original input for 1 character
+ * so there is no amplification and hence recording without
+ * protection. */
+ accountingDiffTolerated(parser, tok, (char *)&ch,
+ ((char *)&ch) + sizeof(XML_Char), __LINE__,
+ XML_ACCOUNT_ENTITY_EXPANSION);
+#endif /* XML_DTD */
if (parser->m_characterDataHandler)
parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
else if (parser->m_defaultHandler)
@@ -2767,7 +2936,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
}
tag->name.str = (XML_Char *)tag->buf;
*toPtr = XML_T('\0');
- result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
+ result
+ = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account);
if (result)
return result;
if (parser->m_startElementHandler)
@@ -2791,7 +2961,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
if (! name.str)
return XML_ERROR_NO_MEMORY;
poolFinish(&parser->m_tempPool);
- result = storeAtts(parser, enc, s, &name, &bindings);
+ result = storeAtts(parser, enc, s, &name, &bindings,
+ XML_ACCOUNT_NONE /* token spans whole start tag */);
if (result != XML_ERROR_NONE) {
freeBindings(parser, bindings);
return result;
@@ -2926,7 +3097,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
/* END disabled code */
else if (parser->m_defaultHandler)
reportDefault(parser, enc, s, next);
- result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
+ result
+ = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account);
if (result != XML_ERROR_NONE)
return result;
else if (! next) {
@@ -3055,7 +3227,8 @@ freeBindings(XML_Parser parser, BINDING *bindings) {
*/
static enum XML_Error
storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
- TAG_NAME *tagNamePtr, BINDING **bindingsPtr) {
+ TAG_NAME *tagNamePtr, BINDING **bindingsPtr,
+ enum XML_Account account) {
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
ELEMENT_TYPE *elementType;
int nDefaultAtts;
@@ -3165,7 +3338,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
/* normalize the attribute value */
result = storeAttributeValue(
parser, enc, isCdata, parser->m_atts[i].valuePtr,
- parser->m_atts[i].valueEnd, &parser->m_tempPool);
+ parser->m_atts[i].valueEnd, &parser->m_tempPool, account);
if (result)
return result;
appAtts[attIndex] = poolStart(&parser->m_tempPool);
@@ -3554,9 +3727,9 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
static enum XML_Error PTRCALL
cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
- enum XML_Error result
- = doCdataSection(parser, parser->m_encoding, &start, end, endPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer);
+ enum XML_Error result = doCdataSection(
+ parser, parser->m_encoding, &start, end, endPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
if (result != XML_ERROR_NONE)
return result;
if (start) {
@@ -3576,7 +3749,8 @@ cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
*/
static enum XML_Error
doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
- const char *end, const char **nextPtr, XML_Bool haveMore) {
+ const char *end, const char **nextPtr, XML_Bool haveMore,
+ enum XML_Account account) {
const char *s = *startPtr;
const char **eventPP;
const char **eventEndPP;
@@ -3594,6 +3768,14 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
for (;;) {
const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
int tok = XmlCdataSectionTok(enc, s, end, &next);
+#ifdef XML_DTD
+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+#else
+ UNUSED_P(account);
+#endif
*eventEndPP = next;
switch (tok) {
case XML_TOK_CDATA_SECT_CLOSE:
@@ -3738,6 +3920,13 @@ doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
*eventPP = s;
*startPtr = NULL;
tok = XmlIgnoreSectionTok(enc, s, end, &next);
+# ifdef XML_DTD
+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
+ XML_ACCOUNT_DIRECT)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+# endif
*eventEndPP = next;
switch (tok) {
case XML_TOK_IGNORE_SECT:
@@ -3822,6 +4011,15 @@ processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
const char *versionend;
const XML_Char *storedversion = NULL;
int standalone = -1;
+
+#ifdef XML_DTD
+ if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__,
+ XML_ACCOUNT_DIRECT)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+#endif
+
if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
&version, &versionend, &encodingName, &newEncoding, &standalone)) {
@@ -3971,6 +4169,10 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
for (;;) {
tok = XmlPrologTok(parser->m_encoding, start, end, &next);
+ /* Note: Except for XML_TOK_BOM below, these bytes are accounted later in:
+ - storeEntityValue
+ - processXmlDecl
+ */
parser->m_eventEndPtr = next;
if (tok <= 0) {
if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
@@ -3989,7 +4191,8 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
break;
}
/* found end of entity value - can store it now */
- return storeEntityValue(parser, parser->m_encoding, s, end);
+ return storeEntityValue(parser, parser->m_encoding, s, end,
+ XML_ACCOUNT_DIRECT);
} else if (tok == XML_TOK_XML_DECL) {
enum XML_Error result;
result = processXmlDecl(parser, 0, start, next);
@@ -4016,6 +4219,14 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
*/
else if (tok == XML_TOK_BOM && next == end
&& ! parser->m_parsingStatus.finalBuffer) {
+# ifdef XML_DTD
+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
+ XML_ACCOUNT_DIRECT)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+# endif
+
*nextPtr = next;
return XML_ERROR_NONE;
}
@@ -4058,16 +4269,24 @@ externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
}
/* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
However, when parsing an external subset, doProlog will not accept a BOM
- as valid, and report a syntax error, so we have to skip the BOM
+ as valid, and report a syntax error, so we have to skip the BOM, and
+ account for the BOM bytes.
*/
else if (tok == XML_TOK_BOM) {
+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
+ XML_ACCOUNT_DIRECT)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+
s = next;
tok = XmlPrologTok(parser->m_encoding, s, end, &next);
}
parser->m_processor = prologProcessor;
return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
+ XML_ACCOUNT_DIRECT);
}
static enum XML_Error PTRCALL
@@ -4080,6 +4299,9 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end,
for (;;) {
tok = XmlPrologTok(enc, start, end, &next);
+ /* Note: These bytes are accounted later in:
+ - storeEntityValue
+ */
if (tok <= 0) {
if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
*nextPtr = s;
@@ -4097,7 +4319,7 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end,
break;
}
/* found end of entity value - can store it now */
- return storeEntityValue(parser, enc, s, end);
+ return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT);
}
start = next;
}
@@ -4111,13 +4333,14 @@ prologProcessor(XML_Parser parser, const char *s, const char *end,
const char *next = s;
int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
+ XML_ACCOUNT_DIRECT);
}
static enum XML_Error
doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
int tok, const char *next, const char **nextPtr, XML_Bool haveMore,
- XML_Bool allowClosingDoctype) {
+ XML_Bool allowClosingDoctype, enum XML_Account account) {
#ifdef XML_DTD
static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
#endif /* XML_DTD */
@@ -4144,6 +4367,10 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
+#ifndef XML_DTD
+ UNUSED_P(account);
+#endif
+
/* save one level of indirection */
DTD *const dtd = parser->m_dtd;
@@ -4208,6 +4435,19 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
}
}
role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
+#ifdef XML_DTD
+ switch (role) {
+ case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor
+ case XML_ROLE_XML_DECL: // bytes accounted in processXmlDecl
+ case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl
+ break;
+ default:
+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+ }
+#endif
switch (role) {
case XML_ROLE_XML_DECL: {
enum XML_Error result = processXmlDecl(parser, 0, s, next);
@@ -4483,7 +4723,8 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
const XML_Char *attVal;
enum XML_Error result = storeAttributeValue(
parser, enc, parser->m_declAttributeIsCdata,
- s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool);
+ s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool,
+ XML_ACCOUNT_NONE);
if (result)
return result;
attVal = poolStart(&dtd->pool);
@@ -4516,8 +4757,9 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
break;
case XML_ROLE_ENTITY_VALUE:
if (dtd->keepProcessing) {
- enum XML_Error result = storeEntityValue(
- parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
+ enum XML_Error result
+ = storeEntityValue(parser, enc, s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
if (parser->m_declEntity) {
parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
parser->m_declEntity->textLen
@@ -4907,12 +5149,15 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
if (parser->m_externalEntityRefHandler) {
dtd->paramEntityRead = XML_FALSE;
entity->open = XML_TRUE;
+ entityTrackingOnOpen(parser, entity, __LINE__);
if (! parser->m_externalEntityRefHandler(
parser->m_externalEntityRefHandlerArg, 0, entity->base,
entity->systemId, entity->publicId)) {
+ entityTrackingOnClose(parser, entity, __LINE__);
entity->open = XML_FALSE;
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
}
+ entityTrackingOnClose(parser, entity, __LINE__);
entity->open = XML_FALSE;
handleDefault = XML_FALSE;
if (! dtd->paramEntityRead) {
@@ -5110,6 +5355,13 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
for (;;) {
const char *next = NULL;
int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
+#ifdef XML_DTD
+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
+ XML_ACCOUNT_DIRECT)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+#endif
parser->m_eventEndPtr = next;
switch (tok) {
/* report partial linebreak - it might be the last token */
@@ -5183,6 +5435,9 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
return XML_ERROR_NO_MEMORY;
}
entity->open = XML_TRUE;
+#ifdef XML_DTD
+ entityTrackingOnOpen(parser, entity, __LINE__);
+#endif
entity->processed = 0;
openEntity->next = parser->m_openInternalEntities;
parser->m_openInternalEntities = openEntity;
@@ -5201,17 +5456,22 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
int tok
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
- tok, next, &next, XML_FALSE, XML_FALSE);
+ tok, next, &next, XML_FALSE, XML_FALSE,
+ XML_ACCOUNT_ENTITY_EXPANSION);
} else
#endif /* XML_DTD */
result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
- textStart, textEnd, &next, XML_FALSE);
+ textStart, textEnd, &next, XML_FALSE,
+ XML_ACCOUNT_ENTITY_EXPANSION);
if (result == XML_ERROR_NONE) {
if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
entity->processed = (int)(next - textStart);
parser->m_processor = internalEntityProcessor;
} else {
+#ifdef XML_DTD
+ entityTrackingOnClose(parser, entity, __LINE__);
+#endif /* XML_DTD */
entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next;
/* put openEntity back in list of free instances */
@@ -5244,12 +5504,13 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
int tok
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
- tok, next, &next, XML_FALSE, XML_TRUE);
+ tok, next, &next, XML_FALSE, XML_TRUE,
+ XML_ACCOUNT_ENTITY_EXPANSION);
} else
#endif /* XML_DTD */
result = doContent(parser, openEntity->startTagLevel,
parser->m_internalEncoding, textStart, textEnd, &next,
- XML_FALSE);
+ XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
if (result != XML_ERROR_NONE)
return result;
@@ -5258,6 +5519,9 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
entity->processed = (int)(next - (const char *)entity->textPtr);
return result;
} else {
+#ifdef XML_DTD
+ entityTrackingOnClose(parser, entity, __LINE__);
+#endif
entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next;
/* put openEntity back in list of free instances */
@@ -5271,7 +5535,8 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
parser->m_processor = prologProcessor;
tok = XmlPrologTok(parser->m_encoding, s, end, &next);
return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
+ XML_ACCOUNT_DIRECT);
} else
#endif /* XML_DTD */
{
@@ -5279,7 +5544,8 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
/* see externalEntityContentProcessor vs contentProcessor */
return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
s, end, nextPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer);
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer,
+ XML_ACCOUNT_DIRECT);
}
}
@@ -5294,9 +5560,10 @@ errorProcessor(XML_Parser parser, const char *s, const char *end,
static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
- const char *ptr, const char *end, STRING_POOL *pool) {
+ const char *ptr, const char *end, STRING_POOL *pool,
+ enum XML_Account account) {
enum XML_Error result
- = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
+ = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
if (result)
return result;
if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
@@ -5308,11 +5575,23 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
- const char *ptr, const char *end, STRING_POOL *pool) {
+ const char *ptr, const char *end, STRING_POOL *pool,
+ enum XML_Account account) {
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
+#ifndef XML_DTD
+ UNUSED_P(account);
+#endif
+
for (;;) {
- const char *next;
+ const char *next
+ = ptr; /* XmlAttributeValueTok doesn't always set the last arg */
int tok = XmlAttributeValueTok(enc, ptr, end, &next);
+#ifdef XML_DTD
+ if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) {
+ accountingOnAbort(parser);
+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ }
+#endif
switch (tok) {
case XML_TOK_NONE:
return XML_ERROR_NONE;
@@ -5372,6 +5651,14 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
XML_Char ch = (XML_Char)XmlPredefinedEntityName(
enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
if (ch) {
+#ifdef XML_DTD
+ /* NOTE: We are replacing 4-6 characters original input for 1 character
+ * so there is no amplification and hence recording without
+ * protection. */
+ accountingDiffTolerated(parser, tok, (char *)&ch,
+ ((char *)&ch) + sizeof(XML_Char), __LINE__,
+ XML_ACCOUNT_ENTITY_EXPANSION);
+#endif /* XML_DTD */
if (! poolAppendChar(pool, ch))
return XML_ERROR_NO_MEMORY;
break;
@@ -5449,9 +5736,16 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
enum XML_Error result;
const XML_Char *textEnd = entity->textPtr + entity->textLen;
entity->open = XML_TRUE;
+#ifdef XML_DTD
+ entityTrackingOnOpen(parser, entity, __LINE__);
+#endif
result = appendAttributeValue(parser, parser->m_internalEncoding,
isCdata, (const char *)entity->textPtr,
- (const char *)textEnd, pool);
+ (const char *)textEnd, pool,
+ XML_ACCOUNT_ENTITY_EXPANSION);
+#ifdef XML_DTD
+ entityTrackingOnClose(parser, entity, __LINE__);
+#endif
entity->open = XML_FALSE;
if (result)
return result;
@@ -5481,13 +5775,16 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
static enum XML_Error
storeEntityValue(XML_Parser parser, const ENCODING *enc,
- const char *entityTextPtr, const char *entityTextEnd) {
+ const char *entityTextPtr, const char *entityTextEnd,
+ enum XML_Account account) {
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
STRING_POOL *pool = &(dtd->entityValuePool);
enum XML_Error result = XML_ERROR_NONE;
#ifdef XML_DTD
int oldInEntityValue = parser->m_prologState.inEntityValue;
parser->m_prologState.inEntityValue = 1;
+#else
+ UNUSED_P(account);
#endif /* XML_DTD */
/* never return Null for the value argument in EntityDeclHandler,
since this would indicate an external entity; therefore we
@@ -5498,8 +5795,19 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
}
for (;;) {
- const char *next;
+ const char *next
+ = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
+
+#ifdef XML_DTD
+ if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__,
+ account)) {
+ accountingOnAbort(parser);
+ result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
+ goto endEntityValue;
+ }
+#endif
+
switch (tok) {
case XML_TOK_PARAM_ENTITY_REF:
#ifdef XML_DTD
@@ -5535,13 +5843,16 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
if (parser->m_externalEntityRefHandler) {
dtd->paramEntityRead = XML_FALSE;
entity->open = XML_TRUE;
+ entityTrackingOnOpen(parser, entity, __LINE__);
if (! parser->m_externalEntityRefHandler(
parser->m_externalEntityRefHandlerArg, 0, entity->base,
entity->systemId, entity->publicId)) {
+ entityTrackingOnClose(parser, entity, __LINE__);
entity->open = XML_FALSE;
result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
goto endEntityValue;
}
+ entityTrackingOnClose(parser, entity, __LINE__);
entity->open = XML_FALSE;
if (! dtd->paramEntityRead)
dtd->keepProcessing = dtd->standalone;
@@ -5549,9 +5860,12 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
dtd->keepProcessing = dtd->standalone;
} else {
entity->open = XML_TRUE;
+ entityTrackingOnOpen(parser, entity, __LINE__);
result = storeEntityValue(
parser, parser->m_internalEncoding, (const char *)entity->textPtr,
- (const char *)(entity->textPtr + entity->textLen));
+ (const char *)(entity->textPtr + entity->textLen),
+ XML_ACCOUNT_ENTITY_EXPANSION);
+ entityTrackingOnClose(parser, entity, __LINE__);
entity->open = XML_FALSE;
if (result)
goto endEntityValue;
@@ -6912,3 +7226,755 @@ copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
memcpy(result, s, charsRequired * sizeof(XML_Char));
return result;
}
+
+#ifdef XML_DTD
+
+static float
+accountingGetCurrentAmplification(XML_Parser rootParser) {
+ const XmlBigCount countBytesOutput
+ = rootParser->m_accounting.countBytesDirect
+ + rootParser->m_accounting.countBytesIndirect;
+ const float amplificationFactor
+ = rootParser->m_accounting.countBytesDirect
+ ? (countBytesOutput
+ / (float)(rootParser->m_accounting.countBytesDirect))
+ : 1.0f;
+ assert(! rootParser->m_parentParser);
+ return amplificationFactor;
+}
+
+static void
+accountingReportStats(XML_Parser originParser, const char *epilog) {
+ const XML_Parser rootParser = getRootParserOf(originParser, NULL);
+ assert(! rootParser->m_parentParser);
+
+ if (rootParser->m_accounting.debugLevel < 1) {
+ return;
+ }
+
+ const float amplificationFactor
+ = accountingGetCurrentAmplification(rootParser);
+ fprintf(stderr,
+ "expat: Accounting(%p): Direct " EXPAT_FMT_ULL(
+ "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s",
+ (void *)rootParser, rootParser->m_accounting.countBytesDirect,
+ rootParser->m_accounting.countBytesIndirect,
+ (double)amplificationFactor, epilog);
+}
+
+static void
+accountingOnAbort(XML_Parser originParser) {
+ accountingReportStats(originParser, " ABORTING\n");
+}
+
+static void
+accountingReportDiff(XML_Parser rootParser,
+ unsigned int levelsAwayFromRootParser, const char *before,
+ const char *after, ptrdiff_t bytesMore, int source_line,
+ enum XML_Account account) {
+ assert(! rootParser->m_parentParser);
+
+ fprintf(stderr,
+ " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"",
+ bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP",
+ levelsAwayFromRootParser, source_line, 10, "");
+
+ const char ellipis[] = "[..]";
+ const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1;
+ const unsigned int contextLength = 10;
+
+ /* Note: Performance is of no concern here */
+ const char *walker = before;
+ if ((rootParser->m_accounting.debugLevel >= 3)
+ || (after - before)
+ <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) {
+ for (; walker < after; walker++) {
+ fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
+ }
+ } else {
+ for (; walker < before + contextLength; walker++) {
+ fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
+ }
+ fprintf(stderr, ellipis);
+ walker = after - contextLength;
+ for (; walker < after; walker++) {
+ fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
+ }
+ }
+ fprintf(stderr, "\"\n");
+}
+
+static XML_Bool
+accountingDiffTolerated(XML_Parser originParser, int tok, const char *before,
+ const char *after, int source_line,
+ enum XML_Account account) {
+ /* Note: We need to check the token type *first* to be sure that
+ * we can even access variable <after>, safely.
+ * E.g. for XML_TOK_NONE <after> may hold an invalid pointer. */
+ switch (tok) {
+ case XML_TOK_INVALID:
+ case XML_TOK_PARTIAL:
+ case XML_TOK_PARTIAL_CHAR:
+ case XML_TOK_NONE:
+ return XML_TRUE;
+ }
+
+ if (account == XML_ACCOUNT_NONE)
+ return XML_TRUE; /* because these bytes have been accounted for, already */
+
+ unsigned int levelsAwayFromRootParser;
+ const XML_Parser rootParser
+ = getRootParserOf(originParser, &levelsAwayFromRootParser);
+ assert(! rootParser->m_parentParser);
+
+ const int isDirect
+ = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser);
+ const ptrdiff_t bytesMore = after - before;
+
+ XmlBigCount *const additionTarget
+ = isDirect ? &rootParser->m_accounting.countBytesDirect
+ : &rootParser->m_accounting.countBytesIndirect;
+
+ /* Detect and avoid integer overflow */
+ if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore)
+ return XML_FALSE;
+ *additionTarget += bytesMore;
+
+ const XmlBigCount countBytesOutput
+ = rootParser->m_accounting.countBytesDirect
+ + rootParser->m_accounting.countBytesIndirect;
+ const float amplificationFactor
+ = accountingGetCurrentAmplification(rootParser);
+ const XML_Bool tolerated
+ = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes)
+ || (amplificationFactor
+ <= rootParser->m_accounting.maximumAmplificationFactor);
+
+ if (rootParser->m_accounting.debugLevel >= 2) {
+ accountingReportStats(rootParser, "");
+ accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after,
+ bytesMore, source_line, account);
+ }
+
+ return tolerated;
+}
+
+unsigned long long
+testingAccountingGetCountBytesDirect(XML_Parser parser) {
+ if (! parser)
+ return 0;
+ return parser->m_accounting.countBytesDirect;
+}
+
+unsigned long long
+testingAccountingGetCountBytesIndirect(XML_Parser parser) {
+ if (! parser)
+ return 0;
+ return parser->m_accounting.countBytesIndirect;
+}
+
+static void
+entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
+ const char *action, int sourceLine) {
+ assert(! rootParser->m_parentParser);
+ if (rootParser->m_entity_stats.debugLevel < 1)
+ return;
+
+# if defined(XML_UNICODE)
+ const char *const entityName = "[..]";
+# else
+ const char *const entityName = entity->name;
+# endif
+
+ fprintf(
+ stderr,
+ "expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n",
+ (void *)rootParser, rootParser->m_entity_stats.countEverOpened,
+ rootParser->m_entity_stats.currentDepth,
+ rootParser->m_entity_stats.maximumDepthSeen,
+ (rootParser->m_entity_stats.currentDepth - 1) * 2, "",
+ entity->is_param ? "%" : "&", entityName, action, entity->textLen,
+ sourceLine);
+}
+
+static void
+entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) {
+ const XML_Parser rootParser = getRootParserOf(originParser, NULL);
+ assert(! rootParser->m_parentParser);
+
+ rootParser->m_entity_stats.countEverOpened++;
+ rootParser->m_entity_stats.currentDepth++;
+ if (rootParser->m_entity_stats.currentDepth
+ > rootParser->m_entity_stats.maximumDepthSeen) {
+ rootParser->m_entity_stats.maximumDepthSeen++;
+ }
+
+ entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine);
+}
+
+static void
+entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) {
+ const XML_Parser rootParser = getRootParserOf(originParser, NULL);
+ assert(! rootParser->m_parentParser);
+
+ entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine);
+ rootParser->m_entity_stats.currentDepth--;
+}
+
+static XML_Parser
+getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {
+ XML_Parser rootParser = parser;
+ unsigned int stepsTakenUpwards = 0;
+ while (rootParser->m_parentParser) {
+ rootParser = rootParser->m_parentParser;
+ stepsTakenUpwards++;
+ }
+ assert(! rootParser->m_parentParser);
+ if (outLevelDiff != NULL) {
+ *outLevelDiff = stepsTakenUpwards;
+ }
+ return rootParser;
+}
+
+const char *
+unsignedCharToPrintable(unsigned char c) {
+ switch (c) {
+ case 0:
+ return "\\0";
+ case 1:
+ return "\\x1";
+ case 2:
+ return "\\x2";
+ case 3:
+ return "\\x3";
+ case 4:
+ return "\\x4";
+ case 5:
+ return "\\x5";
+ case 6:
+ return "\\x6";
+ case 7:
+ return "\\x7";
+ case 8:
+ return "\\x8";
+ case 9:
+ return "\\t";
+ case 10:
+ return "\\n";
+ case 11:
+ return "\\xB";
+ case 12:
+ return "\\xC";
+ case 13:
+ return "\\r";
+ case 14:
+ return "\\xE";
+ case 15:
+ return "\\xF";
+ case 16:
+ return "\\x10";
+ case 17:
+ return "\\x11";
+ case 18:
+ return "\\x12";
+ case 19:
+ return "\\x13";
+ case 20:
+ return "\\x14";
+ case 21:
+ return "\\x15";
+ case 22:
+ return "\\x16";
+ case 23:
+ return "\\x17";
+ case 24:
+ return "\\x18";
+ case 25:
+ return "\\x19";
+ case 26:
+ return "\\x1A";
+ case 27:
+ return "\\x1B";
+ case 28:
+ return "\\x1C";
+ case 29:
+ return "\\x1D";
+ case 30:
+ return "\\x1E";
+ case 31:
+ return "\\x1F";
+ case 32:
+ return " ";
+ case 33:
+ return "!";
+ case 34:
+ return "\\\"";
+ case 35:
+ return "#";
+ case 36:
+ return "$";
+ case 37:
+ return "%";
+ case 38:
+ return "&";
+ case 39:
+ return "'";
+ case 40:
+ return "(";
+ case 41:
+ return ")";
+ case 42:
+ return "*";
+ case 43:
+ return "+";
+ case 44:
+ return ",";
+ case 45:
+ return "-";
+ case 46:
+ return ".";
+ case 47:
+ return "/";
+ case 48:
+ return "0";
+ case 49:
+ return "1";
+ case 50:
+ return "2";
+ case 51:
+ return "3";
+ case 52:
+ return "4";
+ case 53:
+ return "5";
+ case 54:
+ return "6";
+ case 55:
+ return "7";
+ case 56:
+ return "8";
+ case 57:
+ return "9";
+ case 58:
+ return ":";
+ case 59:
+ return ";";
+ case 60:
+ return "<";
+ case 61:
+ return "=";
+ case 62:
+ return ">";
+ case 63:
+ return "?";
+ case 64:
+ return "@";
+ case 65:
+ return "A";
+ case 66:
+ return "B";
+ case 67:
+ return "C";
+ case 68:
+ return "D";
+ case 69:
+ return "E";
+ case 70:
+ return "F";
+ case 71:
+ return "G";
+ case 72:
+ return "H";
+ case 73:
+ return "I";
+ case 74:
+ return "J";
+ case 75:
+ return "K";
+ case 76:
+ return "L";
+ case 77:
+ return "M";
+ case 78:
+ return "N";
+ case 79:
+ return "O";
+ case 80:
+ return "P";
+ case 81:
+ return "Q";
+ case 82:
+ return "R";
+ case 83:
+ return "S";
+ case 84:
+ return "T";
+ case 85:
+ return "U";
+ case 86:
+ return "V";
+ case 87:
+ return "W";
+ case 88:
+ return "X";
+ case 89:
+ return "Y";
+ case 90:
+ return "Z";
+ case 91:
+ return "[";
+ case 92:
+ return "\\\\";
+ case 93:
+ return "]";
+ case 94:
+ return "^";
+ case 95:
+ return "_";
+ case 96:
+ return "`";
+ case 97:
+ return "a";
+ case 98:
+ return "b";
+ case 99:
+ return "c";
+ case 100:
+ return "d";
+ case 101:
+ return "e";
+ case 102:
+ return "f";
+ case 103:
+ return "g";
+ case 104:
+ return "h";
+ case 105:
+ return "i";
+ case 106:
+ return "j";
+ case 107:
+ return "k";
+ case 108:
+ return "l";
+ case 109:
+ return "m";
+ case 110:
+ return "n";
+ case 111:
+ return "o";
+ case 112:
+ return "p";
+ case 113:
+ return "q";
+ case 114:
+ return "r";
+ case 115:
+ return "s";
+ case 116:
+ return "t";
+ case 117:
+ return "u";
+ case 118:
+ return "v";
+ case 119:
+ return "w";
+ case 120:
+ return "x";
+ case 121:
+ return "y";
+ case 122:
+ return "z";
+ case 123:
+ return "{";
+ case 124:
+ return "|";
+ case 125:
+ return "}";
+ case 126:
+ return "~";
+ case 127:
+ return "\\x7F";
+ case 128:
+ return "\\x80";
+ case 129:
+ return "\\x81";
+ case 130:
+ return "\\x82";
+ case 131:
+ return "\\x83";
+ case 132:
+ return "\\x84";
+ case 133:
+ return "\\x85";
+ case 134:
+ return "\\x86";
+ case 135:
+ return "\\x87";
+ case 136:
+ return "\\x88";
+ case 137:
+ return "\\x89";
+ case 138:
+ return "\\x8A";
+ case 139:
+ return "\\x8B";
+ case 140:
+ return "\\x8C";
+ case 141:
+ return "\\x8D";
+ case 142:
+ return "\\x8E";
+ case 143:
+ return "\\x8F";
+ case 144:
+ return "\\x90";
+ case 145:
+ return "\\x91";
+ case 146:
+ return "\\x92";
+ case 147:
+ return "\\x93";
+ case 148:
+ return "\\x94";
+ case 149:
+ return "\\x95";
+ case 150:
+ return "\\x96";
+ case 151:
+ return "\\x97";
+ case 152:
+ return "\\x98";
+ case 153:
+ return "\\x99";
+ case 154:
+ return "\\x9A";
+ case 155:
+ return "\\x9B";
+ case 156:
+ return "\\x9C";
+ case 157:
+ return "\\x9D";
+ case 158:
+ return "\\x9E";
+ case 159:
+ return "\\x9F";
+ case 160:
+ return "\\xA0";
+ case 161:
+ return "\\xA1";
+ case 162:
+ return "\\xA2";
+ case 163:
+ return "\\xA3";
+ case 164:
+ return "\\xA4";
+ case 165:
+ return "\\xA5";
+ case 166:
+ return "\\xA6";
+ case 167:
+ return "\\xA7";
+ case 168:
+ return "\\xA8";
+ case 169:
+ return "\\xA9";
+ case 170:
+ return "\\xAA";
+ case 171:
+ return "\\xAB";
+ case 172:
+ return "\\xAC";
+ case 173:
+ return "\\xAD";
+ case 174:
+ return "\\xAE";
+ case 175:
+ return "\\xAF";
+ case 176:
+ return "\\xB0";
+ case 177:
+ return "\\xB1";
+ case 178:
+ return "\\xB2";
+ case 179:
+ return "\\xB3";
+ case 180:
+ return "\\xB4";
+ case 181:
+ return "\\xB5";
+ case 182:
+ return "\\xB6";
+ case 183:
+ return "\\xB7";
+ case 184:
+ return "\\xB8";
+ case 185:
+ return "\\xB9";
+ case 186:
+ return "\\xBA";
+ case 187:
+ return "\\xBB";
+ case 188:
+ return "\\xBC";
+ case 189:
+ return "\\xBD";
+ case 190:
+ return "\\xBE";
+ case 191:
+ return "\\xBF";
+ case 192:
+ return "\\xC0";
+ case 193:
+ return "\\xC1";
+ case 194:
+ return "\\xC2";
+ case 195:
+ return "\\xC3";
+ case 196:
+ return "\\xC4";
+ case 197:
+ return "\\xC5";
+ case 198:
+ return "\\xC6";
+ case 199:
+ return "\\xC7";
+ case 200:
+ return "\\xC8";
+ case 201:
+ return "\\xC9";
+ case 202:
+ return "\\xCA";
+ case 203:
+ return "\\xCB";
+ case 204:
+ return "\\xCC";
+ case 205:
+ return "\\xCD";
+ case 206:
+ return "\\xCE";
+ case 207:
+ return "\\xCF";
+ case 208:
+ return "\\xD0";
+ case 209:
+ return "\\xD1";
+ case 210:
+ return "\\xD2";
+ case 211:
+ return "\\xD3";
+ case 212:
+ return "\\xD4";
+ case 213:
+ return "\\xD5";
+ case 214:
+ return "\\xD6";
+ case 215:
+ return "\\xD7";
+ case 216:
+ return "\\xD8";
+ case 217:
+ return "\\xD9";
+ case 218:
+ return "\\xDA";
+ case 219:
+ return "\\xDB";
+ case 220:
+ return "\\xDC";
+ case 221:
+ return "\\xDD";
+ case 222:
+ return "\\xDE";
+ case 223:
+ return "\\xDF";
+ case 224:
+ return "\\xE0";
+ case 225:
+ return "\\xE1";
+ case 226:
+ return "\\xE2";
+ case 227:
+ return "\\xE3";
+ case 228:
+ return "\\xE4";
+ case 229:
+ return "\\xE5";
+ case 230:
+ return "\\xE6";
+ case 231:
+ return "\\xE7";
+ case 232:
+ return "\\xE8";
+ case 233:
+ return "\\xE9";
+ case 234:
+ return "\\xEA";
+ case 235:
+ return "\\xEB";
+ case 236:
+ return "\\xEC";
+ case 237:
+ return "\\xED";
+ case 238:
+ return "\\xEE";
+ case 239:
+ return "\\xEF";
+ case 240:
+ return "\\xF0";
+ case 241:
+ return "\\xF1";
+ case 242:
+ return "\\xF2";
+ case 243:
+ return "\\xF3";
+ case 244:
+ return "\\xF4";
+ case 245:
+ return "\\xF5";
+ case 246:
+ return "\\xF6";
+ case 247:
+ return "\\xF7";
+ case 248:
+ return "\\xF8";
+ case 249:
+ return "\\xF9";
+ case 250:
+ return "\\xFA";
+ case 251:
+ return "\\xFB";
+ case 252:
+ return "\\xFC";
+ case 253:
+ return "\\xFD";
+ case 254:
+ return "\\xFE";
+ case 255:
+ return "\\xFF";
+ default:
+ assert(0); /* never gets here */
+ return "dead code";
+ }
+ assert(0); /* never gets here */
+}
+
+#endif /* XML_DTD */
+
+static unsigned long
+getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {
+ const char *const valueOrNull = getenv(variableName);
+ if (valueOrNull == NULL) {
+ return defaultDebugLevel;
+ }
+ const char *const value = valueOrNull;
+
+ errno = 0;
+ char *afterValue = (char *)value;
+ unsigned long debugLevel = strtoul(value, &afterValue, 10);
+ if ((errno != 0) || (afterValue[0] != '\0')) {
+ errno = 0;
+ return defaultDebugLevel;
+ }
+
+ return debugLevel;
+}
diff --git a/Utilities/cmexpat/lib/xmlrole.c b/Utilities/cmexpat/lib/xmlrole.c
index 3b676a415..08173b0fd 100644
--- a/Utilities/cmexpat/lib/xmlrole.c
+++ b/Utilities/cmexpat/lib/xmlrole.c
@@ -7,7 +7,14 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
+ Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2005-2009 Steven Solie <ssolie@users.sourceforge.net>
+ Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
+ Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -34,11 +41,9 @@
#ifdef _WIN32
# include "winconfig.h"
-#else
-# ifdef HAVE_EXPAT_CONFIG_H
-# include <expat_config.h>
-# endif
-#endif /* ndef _WIN32 */
+#endif
+
+#include <expat_config.h>
#include "expat_external.h"
#include "internal.h"
diff --git a/Utilities/cmexpat/lib/xmlrole.h b/Utilities/cmexpat/lib/xmlrole.h
index 036aba64f..d6e1fa150 100644
--- a/Utilities/cmexpat/lib/xmlrole.h
+++ b/Utilities/cmexpat/lib/xmlrole.h
@@ -7,7 +7,10 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/xmltok.c b/Utilities/cmexpat/lib/xmltok.c
index c4f9897f7..f2b6b4060 100644
--- a/Utilities/cmexpat/lib/xmltok.c
+++ b/Utilities/cmexpat/lib/xmltok.c
@@ -7,7 +7,19 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
+ Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2005-2009 Steven Solie <ssolie@users.sourceforge.net>
+ Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016 Pascal Cuoq <cuoq@trust-in-soft.com>
+ Copyright (c) 2016 Don Lewis <truckman@apache.org>
+ Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
+ Copyright (c) 2017 Alexander Bluhm <alexander.bluhm@gmx.net>
+ Copyright (c) 2017 Benbuck Nason <bnason@netflix.com>
+ Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
+ Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -32,23 +44,13 @@
#include <stddef.h>
#include <string.h> /* memcpy */
-
-#if defined(_MSC_VER) && (_MSC_VER <= 1700)
-/* for vs2012/11.0/1700 and earlier Visual Studio compilers */
-# define bool int
-# define false 0
-# define true 1
-#else
-# include <stdbool.h>
-#endif
+#include <stdbool.h>
#ifdef _WIN32
# include "winconfig.h"
-#else
-# ifdef HAVE_EXPAT_CONFIG_H
-# include <expat_config.h>
-# endif
-#endif /* ndef _WIN32 */
+#endif
+
+#include <expat_config.h>
#include "expat_external.h"
#include "internal.h"
@@ -269,8 +271,14 @@ sb_byteToAscii(const ENCODING *enc, const char *p) {
#define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
#define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p))
-#define IS_INVALID_CHAR(enc, p, n) \
- (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
+#ifdef XML_MIN_SIZE
+# define IS_INVALID_CHAR(enc, p, n) \
+ (AS_NORMAL_ENCODING(enc)->isInvalid##n \
+ && AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
+#else
+# define IS_INVALID_CHAR(enc, p, n) \
+ (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
+#endif
#ifdef XML_MIN_SIZE
# define IS_NAME_CHAR_MINBPC(enc, p) \
diff --git a/Utilities/cmexpat/lib/xmltok.h b/Utilities/cmexpat/lib/xmltok.h
index 2adbf5307..6f630c2f9 100644
--- a/Utilities/cmexpat/lib/xmltok.h
+++ b/Utilities/cmexpat/lib/xmltok.h
@@ -7,7 +7,11 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2002-2005 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2016-2017 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/xmltok_impl.c b/Utilities/cmexpat/lib/xmltok_impl.c
index 06d5c9085..0430591b4 100644
--- a/Utilities/cmexpat/lib/xmltok_impl.c
+++ b/Utilities/cmexpat/lib/xmltok_impl.c
@@ -1,4 +1,4 @@
-/* This file is included!
+/* This file is included (from xmltok.c, 1-3 times depending on XML_MIN_SIZE)!
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
@@ -7,7 +7,15 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
+ Copyright (c) 2018 Benjamin Peterson <benjamin@python.org>
+ Copyright (c) 2018 Anton Maklakov <antmak.pub@gmail.com>
+ Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
+ Copyright (c) 2020 Boris Kolpackov <boris@codesynthesis.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -32,7 +40,7 @@
#ifdef XML_TOK_IMPL_C
-# ifndef IS_INVALID_CHAR
+# ifndef IS_INVALID_CHAR // i.e. for UTF-16 and XML_MIN_SIZE not defined
# define IS_INVALID_CHAR(enc, ptr, n) (0)
# endif
diff --git a/Utilities/cmexpat/lib/xmltok_impl.h b/Utilities/cmexpat/lib/xmltok_impl.h
index e925dbc7e..c518aada0 100644
--- a/Utilities/cmexpat/lib/xmltok_impl.h
+++ b/Utilities/cmexpat/lib/xmltok_impl.h
@@ -7,7 +7,8 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2017-2019 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmexpat/lib/xmltok_ns.c b/Utilities/cmexpat/lib/xmltok_ns.c
index 919c74e9f..5fd839223 100644
--- a/Utilities/cmexpat/lib/xmltok_ns.c
+++ b/Utilities/cmexpat/lib/xmltok_ns.c
@@ -7,7 +7,11 @@
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
- Copyright (c) 2000-2017 Expat development team
+ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
+ Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
+ Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/Utilities/cmjsoncpp/CMakeLists.txt b/Utilities/cmjsoncpp/CMakeLists.txt
index 74e998823..029ae860c 100644
--- a/Utilities/cmjsoncpp/CMakeLists.txt
+++ b/Utilities/cmjsoncpp/CMakeLists.txt
@@ -2,7 +2,7 @@ project(JsonCpp CXX)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_CXX_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -woffall")
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
index 8362fc4cb..8291cc654 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
@@ -2,88 +2,74 @@
// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at
-// http://jsoncpp.sourceforge.net/LICENSE
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
-# include <json/assertions.h>
-# include <json/reader.h>
-# include <json/value.h>
-
-# include "json_tool.h"
+#include <json/assertions.h>
+#include <json/reader.h>
+#include <json/value.h>
+#include "json_tool.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <istream>
-#include <limits>
-#include <memory>
-#include <set>
-#include <sstream>
#include <utility>
-
-#include <assert.h>
#include <stdio.h>
+#include <assert.h>
#include <string.h>
+#include <istream>
+#include <sstream>
+#include <memory>
+#include <set>
+#include <limits>
#if defined(_MSC_VER)
-# if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && \
- _MSC_VER >= 1500 // VC++ 9.0 and above
-# define snprintf sprintf_s
-# elif _MSC_VER >= 1900 // VC++ 14.0 and above
-# define snprintf std::snprintf
-# else
-# define snprintf _snprintf
-# endif
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
+#define snprintf _snprintf
+#endif
#elif defined(__ANDROID__) || defined(__QNXNTO__)
-# define snprintf snprintf
+#define snprintf snprintf
#elif __cplusplus >= 201103L
-# if !defined(__MINGW32__) && !defined(__CYGWIN__)
-# define snprintf std::snprintf
-# endif
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
+#define snprintf std::snprintf
+#endif
#endif
#if defined(__QNXNTO__)
-# define sscanf std::sscanf
+#define sscanf std::sscanf
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
// Disable warning about strdup being deprecated.
-# pragma warning(disable : 4996)
+#pragma warning(disable : 4996)
#endif
-// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile
-// time to change the stack limit
+// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
-# define JSONCPP_DEPRECATED_STACK_LIMIT 1000
+#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
#endif
-static size_t const stackLimit_g =
- JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
+static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<CharReader> CharReaderPtr;
#else
-typedef std::auto_ptr<CharReader> CharReaderPtr;
+typedef std::auto_ptr<CharReader> CharReaderPtr;
#endif
// Implementation of class Features
// ////////////////////////////////
Features::Features()
- : allowComments_(true)
- , strictRoot_(false)
- , allowDroppedNullPlaceholders_(false)
- , allowNumericKeys_(false)
-{
-}
+ : allowComments_(true), strictRoot_(false),
+ allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
-Features Features::all()
-{
- return Features();
-}
+Features Features::all() { return Features(); }
-Features Features::strictMode()
-{
+Features Features::strictMode() {
Features features;
features.allowComments_ = false;
features.strictRoot_ = true;
@@ -95,8 +81,7 @@ Features Features::strictMode()
// Implementation of class Reader
// ////////////////////////////////
-bool Reader::containsNewLine(Reader::Location begin, Reader::Location end)
-{
+bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
for (; begin < end; ++begin)
if (*begin == '\n' || *begin == '\r')
return true;
@@ -107,44 +92,24 @@ bool Reader::containsNewLine(Reader::Location begin, Reader::Location end)
// //////////////////////////////////////////////////////////////////
Reader::Reader()
- : errors_()
- , document_()
- , begin_()
- , end_()
- , current_()
- , lastValueEnd_()
- , lastValue_()
- , commentsBefore_()
- , features_(Features::all())
- , collectComments_()
-{
-}
+ : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+ lastValue_(), commentsBefore_(), features_(Features::all()),
+ collectComments_() {}
Reader::Reader(const Features& features)
- : errors_()
- , document_()
- , begin_()
- , end_()
- , current_()
- , lastValueEnd_()
- , lastValue_()
- , commentsBefore_()
- , features_(features)
- , collectComments_()
-{
+ : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+ lastValue_(), commentsBefore_(), features_(features), collectComments_() {
}
-bool Reader::parse(const std::string& document, Value& root,
- bool collectComments)
-{
- this->document_.assign(document.begin(), document.end());
- const char* begin = this->document_.c_str();
- const char* end = begin + this->document_.length();
- return this->parse(begin, end, root, collectComments);
+bool
+Reader::parse(const std::string& document, Value& root, bool collectComments) {
+ document_.assign(document.begin(), document.end());
+ const char* begin = document_.c_str();
+ const char* end = begin + document_.length();
+ return parse(begin, end, root, collectComments);
}
-bool Reader::parse(std::istream& sin, Value& root, bool collectComments)
-{
+bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
// std::istream_iterator<char> begin(sin);
// std::istream_iterator<char> end;
// Those would allow streamed input from a file, if parse() were a
@@ -154,263 +119,257 @@ bool Reader::parse(std::istream& sin, Value& root, bool collectComments)
// create an extra copy.
JSONCPP_STRING doc;
std::getline(sin, doc, (char)EOF);
- return this->parse(doc.data(), doc.data() + doc.size(), root,
- collectComments);
+ return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
}
-bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
- bool collectComments)
-{
- if (!this->features_.allowComments_) {
+bool Reader::parse(const char* beginDoc,
+ const char* endDoc,
+ Value& root,
+ bool collectComments) {
+ if (!features_.allowComments_) {
collectComments = false;
}
- this->begin_ = beginDoc;
- this->end_ = endDoc;
- this->collectComments_ = collectComments;
- this->current_ = this->begin_;
- this->lastValueEnd_ = 0;
- this->lastValue_ = 0;
- this->commentsBefore_.clear();
- this->errors_.clear();
- while (!this->nodes_.empty())
- this->nodes_.pop();
- this->nodes_.push(&root);
-
- bool successful = this->readValue();
+ begin_ = beginDoc;
+ end_ = endDoc;
+ collectComments_ = collectComments;
+ current_ = begin_;
+ lastValueEnd_ = 0;
+ lastValue_ = 0;
+ commentsBefore_.clear();
+ errors_.clear();
+ while (!nodes_.empty())
+ nodes_.pop();
+ nodes_.push(&root);
+
+ bool successful = readValue();
Token token;
- this->skipCommentTokens(token);
- if (this->collectComments_ && !this->commentsBefore_.empty())
- root.setComment(this->commentsBefore_, commentAfter);
- if (this->features_.strictRoot_) {
+ skipCommentTokens(token);
+ if (collectComments_ && !commentsBefore_.empty())
+ root.setComment(commentsBefore_, commentAfter);
+ if (features_.strictRoot_) {
if (!root.isArray() && !root.isObject()) {
- // Set error location to start of doc, ideally should be first token
- // found in doc
+ // Set error location to start of doc, ideally should be first token found
+ // in doc
token.type_ = tokenError;
token.start_ = beginDoc;
token.end_ = endDoc;
- this->addError(
- "A valid JSON document must be either an array or an object value.",
- token);
+ addError(
+ "A valid JSON document must be either an array or an object value.",
+ token);
return false;
}
}
return successful;
}
-bool Reader::readValue()
-{
+bool Reader::readValue() {
// readValue() may call itself only if it calls readObject() or ReadArray().
- // These methods execute nodes_.push() just before and nodes_.pop)() just
- // after calling readValue(). parse() executes one nodes_.push(), so >
- // instead of >=.
- if (this->nodes_.size() > stackLimit_g)
- throwRuntimeError("Exceeded stackLimit in readValue().");
+ // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue().
+ // parse() executes one nodes_.push(), so > instead of >=.
+ if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
- this->skipCommentTokens(token);
+ skipCommentTokens(token);
bool successful = true;
- if (this->collectComments_ && !this->commentsBefore_.empty()) {
- this->currentValue().setComment(this->commentsBefore_, commentBefore);
- this->commentsBefore_.clear();
+ if (collectComments_ && !commentsBefore_.empty()) {
+ currentValue().setComment(commentsBefore_, commentBefore);
+ commentsBefore_.clear();
}
switch (token.type_) {
- case tokenObjectBegin:
- successful = this->readObject(token);
- this->currentValue().setOffsetLimit(this->current_ - this->begin_);
- break;
- case tokenArrayBegin:
- successful = this->readArray(token);
- this->currentValue().setOffsetLimit(this->current_ - this->begin_);
- break;
- case tokenNumber:
- successful = this->decodeNumber(token);
- break;
- case tokenString:
- successful = this->decodeString(token);
- break;
- case tokenTrue: {
- Value v(true);
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- } break;
- case tokenFalse: {
- Value v(false);
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- } break;
- case tokenNull: {
+ case tokenObjectBegin:
+ successful = readObject(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenArrayBegin:
+ successful = readArray(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenNumber:
+ successful = decodeNumber(token);
+ break;
+ case tokenString:
+ successful = decodeString(token);
+ break;
+ case tokenTrue:
+ {
+ Value v(true);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenFalse:
+ {
+ Value v(false);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenNull:
+ {
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenArraySeparator:
+ case tokenObjectEnd:
+ case tokenArrayEnd:
+ if (features_.allowDroppedNullPlaceholders_) {
+ // "Un-read" the current token and mark the current value as a null
+ // token.
+ current_--;
Value v;
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- } break;
- case tokenArraySeparator:
- case tokenObjectEnd:
- case tokenArrayEnd:
- if (this->features_.allowDroppedNullPlaceholders_) {
- // "Un-read" the current token and mark the current value as a null
- // token.
- this->current_--;
- Value v;
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(this->current_ - this->begin_ - 1);
- this->currentValue().setOffsetLimit(this->current_ - this->begin_);
- break;
- } // Else, fall through...
- default:
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- return this->addError("Syntax error: value, object or array expected.",
- token);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(current_ - begin_ - 1);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ } // Else, fall through...
+ default:
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return addError("Syntax error: value, object or array expected.", token);
}
- if (this->collectComments_) {
- this->lastValueEnd_ = this->current_;
- this->lastValue_ = &this->currentValue();
+ if (collectComments_) {
+ lastValueEnd_ = current_;
+ lastValue_ = &currentValue();
}
return successful;
}
-void Reader::skipCommentTokens(Token& token)
-{
- if (this->features_.allowComments_) {
+void Reader::skipCommentTokens(Token& token) {
+ if (features_.allowComments_) {
do {
- this->readToken(token);
+ readToken(token);
} while (token.type_ == tokenComment);
} else {
- this->readToken(token);
+ readToken(token);
}
}
-bool Reader::readToken(Token& token)
-{
- this->skipSpaces();
- token.start_ = this->current_;
- Char c = this->getNextChar();
+bool Reader::readToken(Token& token) {
+ skipSpaces();
+ token.start_ = current_;
+ Char c = getNextChar();
bool ok = true;
switch (c) {
- case '{':
- token.type_ = tokenObjectBegin;
- break;
- case '}':
- token.type_ = tokenObjectEnd;
- break;
- case '[':
- token.type_ = tokenArrayBegin;
- break;
- case ']':
- token.type_ = tokenArrayEnd;
- break;
- case '"':
- token.type_ = tokenString;
- ok = this->readString();
- break;
- case '/':
- token.type_ = tokenComment;
- ok = this->readComment();
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '-':
- token.type_ = tokenNumber;
- this->readNumber();
- break;
- case 't':
- token.type_ = tokenTrue;
- ok = this->match("rue", 3);
- break;
- case 'f':
- token.type_ = tokenFalse;
- ok = this->match("alse", 4);
- break;
- case 'n':
- token.type_ = tokenNull;
- ok = this->match("ull", 3);
- break;
- case ',':
- token.type_ = tokenArraySeparator;
- break;
- case ':':
- token.type_ = tokenMemberSeparator;
- break;
- case 0:
- token.type_ = tokenEndOfStream;
- break;
- default:
- ok = false;
- break;
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = readString();
+ break;
+ case '/':
+ token.type_ = tokenComment;
+ ok = readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ token.type_ = tokenNumber;
+ readNumber();
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = match("rue", 3);
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = match("alse", 4);
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = match("ull", 3);
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
}
if (!ok)
token.type_ = tokenError;
- token.end_ = this->current_;
+ token.end_ = current_;
return true;
}
-void Reader::skipSpaces()
-{
- while (this->current_ != this->end_) {
- Char c = *this->current_;
+void Reader::skipSpaces() {
+ while (current_ != end_) {
+ Char c = *current_;
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
- ++this->current_;
+ ++current_;
else
break;
}
}
-bool Reader::match(Location pattern, int patternLength)
-{
- if (this->end_ - this->current_ < patternLength)
+bool Reader::match(Location pattern, int patternLength) {
+ if (end_ - current_ < patternLength)
return false;
int index = patternLength;
while (index--)
- if (this->current_[index] != pattern[index])
+ if (current_[index] != pattern[index])
return false;
- this->current_ += patternLength;
+ current_ += patternLength;
return true;
}
-bool Reader::readComment()
-{
- Location commentBegin = this->current_ - 1;
- Char c = this->getNextChar();
+bool Reader::readComment() {
+ Location commentBegin = current_ - 1;
+ Char c = getNextChar();
bool successful = false;
if (c == '*')
- successful = this->readCStyleComment();
+ successful = readCStyleComment();
else if (c == '/')
- successful = this->readCppStyleComment();
+ successful = readCppStyleComment();
if (!successful)
return false;
- if (this->collectComments_) {
+ if (collectComments_) {
CommentPlacement placement = commentBefore;
- if (this->lastValueEnd_ &&
- !containsNewLine(this->lastValueEnd_, commentBegin)) {
- if (c != '*' || !containsNewLine(commentBegin, this->current_))
+ if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, current_))
placement = commentAfterOnSameLine;
}
- this->addComment(commentBegin, this->current_, placement);
+ addComment(commentBegin, current_, placement);
}
return true;
}
-JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin,
- Reader::Location end)
-{
+JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
JSONCPP_STRING normalized;
normalized.reserve(static_cast<size_t>(end - begin));
Reader::Location current = begin;
@@ -418,8 +377,8 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin,
char c = *current++;
if (c == '\r') {
if (current != end && *current == '\n')
- // convert dos EOL
- ++current;
+ // convert dos EOL
+ ++current;
// convert Mac EOL
normalized += '\n';
} else {
@@ -429,39 +388,36 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin,
return normalized;
}
-void Reader::addComment(Location begin, Location end,
- CommentPlacement placement)
-{
- assert(this->collectComments_);
+void
+Reader::addComment(Location begin, Location end, CommentPlacement placement) {
+ assert(collectComments_);
const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
- assert(this->lastValue_ != 0);
- this->lastValue_->setComment(normalized, placement);
+ assert(lastValue_ != 0);
+ lastValue_->setComment(normalized, placement);
} else {
- this->commentsBefore_ += normalized;
+ commentsBefore_ += normalized;
}
}
-bool Reader::readCStyleComment()
-{
- while ((this->current_ + 1) < this->end_) {
- Char c = this->getNextChar();
- if (c == '*' && *this->current_ == '/')
+bool Reader::readCStyleComment() {
+ while ((current_ + 1) < end_) {
+ Char c = getNextChar();
+ if (c == '*' && *current_ == '/')
break;
}
- return this->getNextChar() == '/';
+ return getNextChar() == '/';
}
-bool Reader::readCppStyleComment()
-{
- while (this->current_ != this->end_) {
- Char c = this->getNextChar();
+bool Reader::readCppStyleComment() {
+ while (current_ != end_) {
+ Char c = getNextChar();
if (c == '\n')
break;
if (c == '\r') {
// Consume DOS EOL. It will be normalized in addComment.
- if (this->current_ != this->end_ && *this->current_ == '\n')
- this->getNextChar();
+ if (current_ != end_ && *current_ == '\n')
+ getNextChar();
// Break on Moc OS 9 EOL.
break;
}
@@ -469,132 +425,127 @@ bool Reader::readCppStyleComment()
return true;
}
-void Reader::readNumber()
-{
- const char* p = this->current_;
+void Reader::readNumber() {
+ const char *p = current_;
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
// fractional part
if (c == '.') {
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
}
// exponential part
if (c == 'e' || c == 'E') {
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
if (c == '+' || c == '-')
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
}
}
-bool Reader::readString()
-{
+bool Reader::readString() {
Char c = '\0';
- while (this->current_ != this->end_) {
- c = this->getNextChar();
+ while (current_ != end_) {
+ c = getNextChar();
if (c == '\\')
- this->getNextChar();
+ getNextChar();
else if (c == '"')
break;
}
return c == '"';
}
-bool Reader::readObject(Token& tokenStart)
-{
+bool Reader::readObject(Token& tokenStart) {
Token tokenName;
JSONCPP_STRING name;
Value init(objectValue);
- this->currentValue().swapPayload(init);
- this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
- while (this->readToken(tokenName)) {
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ while (readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
- initialTokenOk = this->readToken(tokenName);
+ initialTokenOk = readToken(tokenName);
if (!initialTokenOk)
break;
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
return true;
name.clear();
if (tokenName.type_ == tokenString) {
- if (!this->decodeString(tokenName, name))
- return this->recoverFromError(tokenObjectEnd);
- } else if (tokenName.type_ == tokenNumber &&
- this->features_.allowNumericKeys_) {
+ if (!decodeString(tokenName, name))
+ return recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
Value numberName;
- if (!this->decodeNumber(tokenName, numberName))
- return this->recoverFromError(tokenObjectEnd);
+ if (!decodeNumber(tokenName, numberName))
+ return recoverFromError(tokenObjectEnd);
name = JSONCPP_STRING(numberName.asCString());
} else {
break;
}
Token colon;
- if (!this->readToken(colon) || colon.type_ != tokenMemberSeparator) {
- return this->addErrorAndRecover("Missing ':' after object member name",
- colon, tokenObjectEnd);
+ if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return addErrorAndRecover(
+ "Missing ':' after object member name", colon, tokenObjectEnd);
}
- Value& value = this->currentValue()[name];
- this->nodes_.push(&value);
- bool ok = this->readValue();
- this->nodes_.pop();
+ Value& value = currentValue()[name];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
if (!ok) // error already set
- return this->recoverFromError(tokenObjectEnd);
+ return recoverFromError(tokenObjectEnd);
Token comma;
- if (!this->readToken(comma) ||
+ if (!readToken(comma) ||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment)) {
- return this->addErrorAndRecover(
- "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ return addErrorAndRecover(
+ "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
}
bool finalizeTokenOk = true;
while (comma.type_ == tokenComment && finalizeTokenOk)
- finalizeTokenOk = this->readToken(comma);
+ finalizeTokenOk = readToken(comma);
if (comma.type_ == tokenObjectEnd)
return true;
}
- return this->addErrorAndRecover("Missing '}' or object member name",
- tokenName, tokenObjectEnd);
+ return addErrorAndRecover(
+ "Missing '}' or object member name", tokenName, tokenObjectEnd);
}
-bool Reader::readArray(Token& tokenStart)
-{
+bool Reader::readArray(Token& tokenStart) {
Value init(arrayValue);
- this->currentValue().swapPayload(init);
- this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
- this->skipSpaces();
- if (this->current_ != this->end_ && *this->current_ == ']') // empty array
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ skipSpaces();
+ if (current_ != end_ && *current_ == ']') // empty array
{
Token endArray;
- this->readToken(endArray);
+ readToken(endArray);
return true;
}
int index = 0;
for (;;) {
- Value& value = this->currentValue()[index++];
- this->nodes_.push(&value);
- bool ok = this->readValue();
- this->nodes_.pop();
+ Value& value = currentValue()[index++];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
if (!ok) // error already set
- return this->recoverFromError(tokenArrayEnd);
+ return recoverFromError(tokenArrayEnd);
Token token;
// Accept Comment after last item in the array.
- ok = this->readToken(token);
+ ok = readToken(token);
while (token.type_ == tokenComment && ok) {
- ok = this->readToken(token);
+ ok = readToken(token);
}
bool badTokenType =
- (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
if (!ok || badTokenType) {
- return this->addErrorAndRecover(
- "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ return addErrorAndRecover(
+ "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
}
if (token.type_ == tokenArrayEnd)
break;
@@ -602,19 +553,17 @@ bool Reader::readArray(Token& tokenStart)
return true;
}
-bool Reader::decodeNumber(Token& token)
-{
+bool Reader::decodeNumber(Token& token) {
Value decoded;
- if (!this->decodeNumber(token, decoded))
+ if (!decodeNumber(token, decoded))
return false;
- this->currentValue().swapPayload(decoded);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
-bool Reader::decodeNumber(Token& token, Value& decoded)
-{
+bool Reader::decodeNumber(Token& token, Value& decoded) {
// Attempts to parse the number as an integer. If the number is
// larger than the maximum supported value of an integer then
// we decode the number as a double.
@@ -622,17 +571,16 @@ bool Reader::decodeNumber(Token& token, Value& decoded)
bool isNegative = *current == '-';
if (isNegative)
++current;
- // TODO: Help the compiler do the div and mod at compile time or get rid of
- // them.
- Value::LargestUInt maxIntegerValue = isNegative
- ? Value::LargestUInt(Value::maxLargestInt) + 1
- : Value::maxLargestUInt;
+ // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+ Value::LargestUInt maxIntegerValue =
+ isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
+ : Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
Value::LargestUInt value = 0;
while (current < token.end_) {
Char c = *current++;
if (c < '0' || c > '9')
- return this->decodeDouble(token, decoded);
+ return decodeDouble(token, decoded);
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If
@@ -641,7 +589,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded)
// Otherwise treat this number as a double to avoid overflow.
if (value > threshold || current != token.end_ ||
digit > maxIntegerValue % 10) {
- return this->decodeDouble(token, decoded);
+ return decodeDouble(token, decoded);
}
}
value = value * 10 + digit;
@@ -657,44 +605,40 @@ bool Reader::decodeNumber(Token& token, Value& decoded)
return true;
}
-bool Reader::decodeDouble(Token& token)
-{
+bool Reader::decodeDouble(Token& token) {
Value decoded;
- if (!this->decodeDouble(token, decoded))
+ if (!decodeDouble(token, decoded))
return false;
- this->currentValue().swapPayload(decoded);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
-bool Reader::decodeDouble(Token& token, Value& decoded)
-{
+bool Reader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
JSONCPP_STRING buffer(token.start_, token.end_);
JSONCPP_ISTRINGSTREAM is(buffer);
if (!(is >> value))
- return this->addError("'" + JSONCPP_STRING(token.start_, token.end_) +
- "' is not a number.",
- token);
+ return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
+ "' is not a number.",
+ token);
decoded = value;
return true;
}
-bool Reader::decodeString(Token& token)
-{
+bool Reader::decodeString(Token& token) {
JSONCPP_STRING decoded_string;
- if (!this->decodeString(token, decoded_string))
+ if (!decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
- this->currentValue().swapPayload(decoded);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
-bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded)
-{
+bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
@@ -704,43 +648,41 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded)
break;
else if (c == '\\') {
if (current == end)
- return this->addError("Empty escape sequence in string", token,
- current);
+ return addError("Empty escape sequence in string", token, current);
Char escape = *current++;
switch (escape) {
- case '"':
- decoded += '"';
- break;
- case '/':
- decoded += '/';
- break;
- case '\\':
- decoded += '\\';
- break;
- case 'b':
- decoded += '\b';
- break;
- case 'f':
- decoded += '\f';
- break;
- case 'n':
- decoded += '\n';
- break;
- case 'r':
- decoded += '\r';
- break;
- case 't':
- decoded += '\t';
- break;
- case 'u': {
- unsigned int unicode;
- if (!this->decodeUnicodeCodePoint(token, current, end, unicode))
- return false;
- decoded += codePointToUTF8(unicode);
- } break;
- default:
- return this->addError("Bad escape sequence in string", token,
- current);
+ case '"':
+ decoded += '"';
+ break;
+ case '/':
+ decoded += '/';
+ break;
+ case '\\':
+ decoded += '\\';
+ break;
+ case 'b':
+ decoded += '\b';
+ break;
+ case 'f':
+ decoded += '\f';
+ break;
+ case 'n':
+ decoded += '\n';
+ break;
+ case 'r':
+ decoded += '\r';
+ break;
+ case 't':
+ decoded += '\t';
+ break;
+ case 'u': {
+ unsigned int unicode;
+ if (!decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return addError("Bad escape sequence in string", token, current);
}
} else {
decoded += c;
@@ -749,43 +691,44 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded)
return true;
}
-bool Reader::decodeUnicodeCodePoint(Token& token, Location& current,
- Location end, unsigned int& unicode)
-{
+bool Reader::decodeUnicodeCodePoint(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode) {
- if (!this->decodeUnicodeEscapeSequence(token, current, end, unicode))
+ if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
return false;
if (unicode >= 0xD800 && unicode <= 0xDBFF) {
// surrogate pairs
if (end - current < 6)
- return this->addError(
- "additional six characters expected to parse unicode surrogate pair.",
- token, current);
+ return addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token,
+ current);
unsigned int surrogatePair;
if (*(current++) == '\\' && *(current++) == 'u') {
- if (this->decodeUnicodeEscapeSequence(token, current, end,
- surrogatePair)) {
- unicode =
- 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
return false;
} else
- return this->addError(
- "expecting another \\u token to begin the second half of "
- "a unicode surrogate pair",
- token, current);
+ return addError("expecting another \\u token to begin the second half of "
+ "a unicode surrogate pair",
+ token,
+ current);
}
return true;
}
-bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current,
+bool Reader::decodeUnicodeEscapeSequence(Token& token,
+ Location& current,
Location end,
- unsigned int& ret_unicode)
-{
+ unsigned int& ret_unicode) {
if (end - current < 4)
- return this->addError(
- "Bad unicode escape sequence in string: four digits expected.", token,
- current);
+ return addError(
+ "Bad unicode escape sequence in string: four digits expected.",
+ token,
+ current);
int unicode = 0;
for (int index = 0; index < 4; ++index) {
Char c = *current++;
@@ -797,65 +740,60 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current,
else if (c >= 'A' && c <= 'F')
unicode += c - 'A' + 10;
else
- return this->addError(
- "Bad unicode escape sequence in string: hexadecimal digit expected.",
- token, current);
+ return addError(
+ "Bad unicode escape sequence in string: hexadecimal digit expected.",
+ token,
+ current);
}
ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
-bool Reader::addError(const JSONCPP_STRING& message, Token& token,
- Location extra)
-{
+bool
+Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = extra;
- this->errors_.push_back(info);
+ errors_.push_back(info);
return false;
}
-bool Reader::recoverFromError(TokenType skipUntilToken)
-{
- size_t const errorCount = this->errors_.size();
+bool Reader::recoverFromError(TokenType skipUntilToken) {
+ size_t const errorCount = errors_.size();
Token skip;
for (;;) {
- if (!this->readToken(skip))
- this->errors_.resize(errorCount); // discard errors caused by recovery
+ if (!readToken(skip))
+ errors_.resize(errorCount); // discard errors caused by recovery
if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
break;
}
- this->errors_.resize(errorCount);
+ errors_.resize(errorCount);
return false;
}
-bool Reader::addErrorAndRecover(const JSONCPP_STRING& message, Token& token,
- TokenType skipUntilToken)
-{
- this->addError(message, token);
- return this->recoverFromError(skipUntilToken);
+bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
+ Token& token,
+ TokenType skipUntilToken) {
+ addError(message, token);
+ return recoverFromError(skipUntilToken);
}
-Value& Reader::currentValue()
-{
- return *(this->nodes_.top());
-}
+Value& Reader::currentValue() { return *(nodes_.top()); }
-Reader::Char Reader::getNextChar()
-{
- if (this->current_ == this->end_)
+Reader::Char Reader::getNextChar() {
+ if (current_ == end_)
return 0;
- return *this->current_++;
+ return *current_++;
}
-void Reader::getLocationLineAndColumn(Location location, int& line,
- int& column) const
-{
- Location current = this->begin_;
+void Reader::getLocationLineAndColumn(Location location,
+ int& line,
+ int& column) const {
+ Location current = begin_;
Location lastLineStart = current;
line = 0;
- while (current < location && current != this->end_) {
+ while (current < location && current != end_) {
Char c = *current++;
if (c == '\r') {
if (*current == '\n')
@@ -872,96 +810,91 @@ void Reader::getLocationLineAndColumn(Location location, int& line,
++line;
}
-JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const
-{
+JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
int line, column;
- this->getLocationLineAndColumn(location, line, column);
+ getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
return buffer;
}
// Deprecated. Preserved for backward compatibility
-JSONCPP_STRING Reader::getFormatedErrorMessages() const
-{
- return this->getFormattedErrorMessages();
+JSONCPP_STRING Reader::getFormatedErrorMessages() const {
+ return getFormattedErrorMessages();
}
-JSONCPP_STRING Reader::getFormattedErrorMessages() const
-{
+JSONCPP_STRING Reader::getFormattedErrorMessages() const {
JSONCPP_STRING formattedMessage;
- for (Errors::const_iterator itError = this->errors_.begin();
- itError != this->errors_.end(); ++itError) {
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
const ErrorInfo& error = *itError;
formattedMessage +=
- "* " + this->getLocationLineAndColumn(error.token_.start_) + "\n";
+ "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
if (error.extra_)
- formattedMessage += "See " +
- this->getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ formattedMessage +=
+ "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
}
return formattedMessage;
}
-std::vector<Reader::StructuredError> Reader::getStructuredErrors() const
-{
+std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
std::vector<Reader::StructuredError> allErrors;
- for (Errors::const_iterator itError = this->errors_.begin();
- itError != this->errors_.end(); ++itError) {
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
const ErrorInfo& error = *itError;
Reader::StructuredError structured;
- structured.offset_start = error.token_.start_ - this->begin_;
- structured.offset_limit = error.token_.end_ - this->begin_;
+ structured.offset_start = error.token_.start_ - begin_;
+ structured.offset_limit = error.token_.end_ - begin_;
structured.message = error.message_;
allErrors.push_back(structured);
}
return allErrors;
}
-bool Reader::pushError(const Value& value, const JSONCPP_STRING& message)
-{
- ptrdiff_t const length = this->end_ - this->begin_;
- if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
+ ptrdiff_t const length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = this->begin_ + value.getOffsetStart();
- token.end_ = this->end_ + value.getOffsetLimit();
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = end_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = 0;
- this->errors_.push_back(info);
+ errors_.push_back(info);
return true;
}
-bool Reader::pushError(const Value& value, const JSONCPP_STRING& message,
- const Value& extra)
-{
- ptrdiff_t const length = this->end_ - this->begin_;
- if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
- extra.getOffsetLimit() > length)
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
+ ptrdiff_t const length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length
+ || extra.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = this->begin_ + value.getOffsetStart();
- token.end_ = this->begin_ + value.getOffsetLimit();
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = begin_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
- info.extra_ = this->begin_ + extra.getOffsetStart();
- this->errors_.push_back(info);
+ info.extra_ = begin_ + extra.getOffsetStart();
+ errors_.push_back(info);
return true;
}
-bool Reader::good() const
-{
- return !this->errors_.size();
+bool Reader::good() const {
+ return !errors_.size();
}
// exact copy of Features
-class OurFeatures
-{
+class OurFeatures {
public:
static OurFeatures all();
bool allowComments_;
@@ -973,48 +906,43 @@ public:
bool rejectDupKeys_;
bool allowSpecialFloats_;
int stackLimit_;
-}; // OurFeatures
+}; // OurFeatures
// exact copy of Implementation of class Features
// ////////////////////////////////
-OurFeatures OurFeatures::all()
-{
- return OurFeatures();
-}
+OurFeatures OurFeatures::all() { return OurFeatures(); }
// Implementation of class Reader
// ////////////////////////////////
// exact copy of Reader, renamed to OurReader
-class OurReader
-{
+class OurReader {
public:
typedef char Char;
typedef const Char* Location;
- struct StructuredError
- {
+ struct StructuredError {
ptrdiff_t offset_start;
ptrdiff_t offset_limit;
JSONCPP_STRING message;
};
OurReader(OurFeatures const& features);
- bool parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool parse(const char* beginDoc,
+ const char* endDoc,
+ Value& root,
bool collectComments = true);
JSONCPP_STRING getFormattedErrorMessages() const;
std::vector<StructuredError> getStructuredErrors() const;
bool pushError(const Value& value, const JSONCPP_STRING& message);
- bool pushError(const Value& value, const JSONCPP_STRING& message,
- const Value& extra);
+ bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
bool good() const;
private:
- OurReader(OurReader const&); // no impl
- void operator=(OurReader const&); // no impl
+ OurReader(OurReader const&); // no impl
+ void operator=(OurReader const&); // no impl
- enum TokenType
- {
+ enum TokenType {
tokenEndOfStream = 0,
tokenObjectBegin,
tokenObjectEnd,
@@ -1034,16 +962,14 @@ private:
tokenError
};
- class Token
- {
+ class Token {
public:
TokenType type_;
Location start_;
Location end_;
};
- class ErrorInfo
- {
+ class ErrorInfo {
public:
Token token_;
JSONCPP_STRING message_;
@@ -1070,20 +996,24 @@ private:
bool decodeString(Token& token, JSONCPP_STRING& decoded);
bool decodeDouble(Token& token);
bool decodeDouble(Token& token, Value& decoded);
- bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
+ bool decodeUnicodeCodePoint(Token& token,
+ Location& current,
+ Location end,
unsigned int& unicode);
- bool decodeUnicodeEscapeSequence(Token& token, Location& current,
- Location end, unsigned int& unicode);
- bool addError(const JSONCPP_STRING& message, Token& token,
- Location extra = 0);
+ bool decodeUnicodeEscapeSequence(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode);
+ bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
bool recoverFromError(TokenType skipUntilToken);
- bool addErrorAndRecover(const JSONCPP_STRING& message, Token& token,
+ bool addErrorAndRecover(const JSONCPP_STRING& message,
+ Token& token,
TokenType skipUntilToken);
void skipUntilSpace();
Value& currentValue();
Char getNextChar();
- void getLocationLineAndColumn(Location location, int& line,
- int& column) const;
+ void
+ getLocationLineAndColumn(Location location, int& line, int& column) const;
JSONCPP_STRING getLocationLineAndColumn(Location location) const;
void addComment(Location begin, Location end, CommentPlacement placement);
void skipCommentTokens(Token& token);
@@ -1104,13 +1034,11 @@ private:
OurFeatures const features_;
bool collectComments_;
-}; // OurReader
+}; // OurReader
// complete copy of Read impl, for OurReader
-bool OurReader::containsNewLine(OurReader::Location begin,
- OurReader::Location end)
-{
+bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) {
for (; begin < end; ++begin)
if (*begin == '\n' || *begin == '\r')
return true;
@@ -1118,322 +1046,315 @@ bool OurReader::containsNewLine(OurReader::Location begin,
}
OurReader::OurReader(OurFeatures const& features)
- : errors_()
- , document_()
- , begin_()
- , end_()
- , current_()
- , lastValueEnd_()
- , lastValue_()
- , commentsBefore_()
- , features_(features)
- , collectComments_()
-{
+ : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+ lastValue_(), commentsBefore_(),
+ features_(features), collectComments_() {
}
-bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
- bool collectComments)
-{
- if (!this->features_.allowComments_) {
+bool OurReader::parse(const char* beginDoc,
+ const char* endDoc,
+ Value& root,
+ bool collectComments) {
+ if (!features_.allowComments_) {
collectComments = false;
}
- this->begin_ = beginDoc;
- this->end_ = endDoc;
- this->collectComments_ = collectComments;
- this->current_ = this->begin_;
- this->lastValueEnd_ = 0;
- this->lastValue_ = 0;
- this->commentsBefore_.clear();
- this->errors_.clear();
- while (!this->nodes_.empty())
- this->nodes_.pop();
- this->nodes_.push(&root);
-
- bool successful = this->readValue();
+ begin_ = beginDoc;
+ end_ = endDoc;
+ collectComments_ = collectComments;
+ current_ = begin_;
+ lastValueEnd_ = 0;
+ lastValue_ = 0;
+ commentsBefore_.clear();
+ errors_.clear();
+ while (!nodes_.empty())
+ nodes_.pop();
+ nodes_.push(&root);
+
+ bool successful = readValue();
Token token;
- this->skipCommentTokens(token);
- if (this->features_.failIfExtra_) {
- if ((this->features_.strictRoot_ || token.type_ != tokenError) &&
- token.type_ != tokenEndOfStream) {
- this->addError("Extra non-whitespace after JSON value.", token);
+ skipCommentTokens(token);
+ if (features_.failIfExtra_) {
+ if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
+ addError("Extra non-whitespace after JSON value.", token);
return false;
}
}
- if (this->collectComments_ && !this->commentsBefore_.empty())
- root.setComment(this->commentsBefore_, commentAfter);
- if (this->features_.strictRoot_) {
+ if (collectComments_ && !commentsBefore_.empty())
+ root.setComment(commentsBefore_, commentAfter);
+ if (features_.strictRoot_) {
if (!root.isArray() && !root.isObject()) {
- // Set error location to start of doc, ideally should be first token
- // found in doc
+ // Set error location to start of doc, ideally should be first token found
+ // in doc
token.type_ = tokenError;
token.start_ = beginDoc;
token.end_ = endDoc;
- this->addError(
- "A valid JSON document must be either an array or an object value.",
- token);
+ addError(
+ "A valid JSON document must be either an array or an object value.",
+ token);
return false;
}
}
return successful;
}
-bool OurReader::readValue()
-{
+bool OurReader::readValue() {
// To preserve the old behaviour we cast size_t to int.
- if (static_cast<int>(this->nodes_.size()) > this->features_.stackLimit_)
- throwRuntimeError("Exceeded stackLimit in readValue().");
+ if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
- this->skipCommentTokens(token);
+ skipCommentTokens(token);
bool successful = true;
- if (this->collectComments_ && !this->commentsBefore_.empty()) {
- this->currentValue().setComment(this->commentsBefore_, commentBefore);
- this->commentsBefore_.clear();
+ if (collectComments_ && !commentsBefore_.empty()) {
+ currentValue().setComment(commentsBefore_, commentBefore);
+ commentsBefore_.clear();
}
switch (token.type_) {
- case tokenObjectBegin:
- successful = this->readObject(token);
- this->currentValue().setOffsetLimit(this->current_ - this->begin_);
- break;
- case tokenArrayBegin:
- successful = this->readArray(token);
- this->currentValue().setOffsetLimit(this->current_ - this->begin_);
- break;
- case tokenNumber:
- successful = this->decodeNumber(token);
- break;
- case tokenString:
- successful = this->decodeString(token);
- break;
- case tokenTrue: {
- Value v(true);
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- } break;
- case tokenFalse: {
- Value v(false);
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- } break;
- case tokenNull: {
+ case tokenObjectBegin:
+ successful = readObject(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenArrayBegin:
+ successful = readArray(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenNumber:
+ successful = decodeNumber(token);
+ break;
+ case tokenString:
+ successful = decodeString(token);
+ break;
+ case tokenTrue:
+ {
+ Value v(true);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenFalse:
+ {
+ Value v(false);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenNull:
+ {
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenNaN:
+ {
+ Value v(std::numeric_limits<double>::quiet_NaN());
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenPosInf:
+ {
+ Value v(std::numeric_limits<double>::infinity());
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenNegInf:
+ {
+ Value v(-std::numeric_limits<double>::infinity());
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenArraySeparator:
+ case tokenObjectEnd:
+ case tokenArrayEnd:
+ if (features_.allowDroppedNullPlaceholders_) {
+ // "Un-read" the current token and mark the current value as a null
+ // token.
+ current_--;
Value v;
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- } break;
- case tokenNaN: {
- Value v(std::numeric_limits<double>::quiet_NaN());
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- } break;
- case tokenPosInf: {
- Value v(std::numeric_limits<double>::infinity());
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- } break;
- case tokenNegInf: {
- Value v(-std::numeric_limits<double>::infinity());
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- } break;
- case tokenArraySeparator:
- case tokenObjectEnd:
- case tokenArrayEnd:
- if (this->features_.allowDroppedNullPlaceholders_) {
- // "Un-read" the current token and mark the current value as a null
- // token.
- this->current_--;
- Value v;
- this->currentValue().swapPayload(v);
- this->currentValue().setOffsetStart(this->current_ - this->begin_ - 1);
- this->currentValue().setOffsetLimit(this->current_ - this->begin_);
- break;
- } // else, fall through ...
- default:
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
- return this->addError("Syntax error: value, object or array expected.",
- token);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(current_ - begin_ - 1);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ } // else, fall through ...
+ default:
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return addError("Syntax error: value, object or array expected.", token);
}
- if (this->collectComments_) {
- this->lastValueEnd_ = this->current_;
- this->lastValue_ = &this->currentValue();
+ if (collectComments_) {
+ lastValueEnd_ = current_;
+ lastValue_ = &currentValue();
}
return successful;
}
-void OurReader::skipCommentTokens(Token& token)
-{
- if (this->features_.allowComments_) {
+void OurReader::skipCommentTokens(Token& token) {
+ if (features_.allowComments_) {
do {
- this->readToken(token);
+ readToken(token);
} while (token.type_ == tokenComment);
} else {
- this->readToken(token);
+ readToken(token);
}
}
-bool OurReader::readToken(Token& token)
-{
- this->skipSpaces();
- token.start_ = this->current_;
- Char c = this->getNextChar();
+bool OurReader::readToken(Token& token) {
+ skipSpaces();
+ token.start_ = current_;
+ Char c = getNextChar();
bool ok = true;
switch (c) {
- case '{':
- token.type_ = tokenObjectBegin;
- break;
- case '}':
- token.type_ = tokenObjectEnd;
- break;
- case '[':
- token.type_ = tokenArrayBegin;
- break;
- case ']':
- token.type_ = tokenArrayEnd;
- break;
- case '"':
- token.type_ = tokenString;
- ok = this->readString();
- break;
- case '\'':
- if (this->features_.allowSingleQuotes_) {
- token.type_ = tokenString;
- ok = this->readStringSingleQuote();
- break;
- } // else continue
- case '/':
- token.type_ = tokenComment;
- ok = this->readComment();
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = readString();
+ break;
+ case '\'':
+ if (features_.allowSingleQuotes_) {
+ token.type_ = tokenString;
+ ok = readStringSingleQuote();
+ break;
+ } // else continue
+ case '/':
+ token.type_ = tokenComment;
+ ok = readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ token.type_ = tokenNumber;
+ readNumber(false);
+ break;
+ case '-':
+ if (readNumber(true)) {
token.type_ = tokenNumber;
- this->readNumber(false);
- break;
- case '-':
- if (this->readNumber(true)) {
- token.type_ = tokenNumber;
- } else {
- token.type_ = tokenNegInf;
- ok = this->features_.allowSpecialFloats_ && this->match("nfinity", 7);
- }
- break;
- case 't':
- token.type_ = tokenTrue;
- ok = this->match("rue", 3);
- break;
- case 'f':
- token.type_ = tokenFalse;
- ok = this->match("alse", 4);
- break;
- case 'n':
- token.type_ = tokenNull;
- ok = this->match("ull", 3);
- break;
- case 'N':
- if (this->features_.allowSpecialFloats_) {
- token.type_ = tokenNaN;
- ok = this->match("aN", 2);
- } else {
- ok = false;
- }
- break;
- case 'I':
- if (this->features_.allowSpecialFloats_) {
- token.type_ = tokenPosInf;
- ok = this->match("nfinity", 7);
- } else {
- ok = false;
- }
- break;
- case ',':
- token.type_ = tokenArraySeparator;
- break;
- case ':':
- token.type_ = tokenMemberSeparator;
- break;
- case 0:
- token.type_ = tokenEndOfStream;
- break;
- default:
+ } else {
+ token.type_ = tokenNegInf;
+ ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+ }
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = match("rue", 3);
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = match("alse", 4);
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = match("ull", 3);
+ break;
+ case 'N':
+ if (features_.allowSpecialFloats_) {
+ token.type_ = tokenNaN;
+ ok = match("aN", 2);
+ } else {
ok = false;
- break;
+ }
+ break;
+ case 'I':
+ if (features_.allowSpecialFloats_) {
+ token.type_ = tokenPosInf;
+ ok = match("nfinity", 7);
+ } else {
+ ok = false;
+ }
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
}
if (!ok)
token.type_ = tokenError;
- token.end_ = this->current_;
+ token.end_ = current_;
return true;
}
-void OurReader::skipSpaces()
-{
- while (this->current_ != this->end_) {
- Char c = *this->current_;
+void OurReader::skipSpaces() {
+ while (current_ != end_) {
+ Char c = *current_;
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
- ++this->current_;
+ ++current_;
else
break;
}
}
-bool OurReader::match(Location pattern, int patternLength)
-{
- if (this->end_ - this->current_ < patternLength)
+bool OurReader::match(Location pattern, int patternLength) {
+ if (end_ - current_ < patternLength)
return false;
int index = patternLength;
while (index--)
- if (this->current_[index] != pattern[index])
+ if (current_[index] != pattern[index])
return false;
- this->current_ += patternLength;
+ current_ += patternLength;
return true;
}
-bool OurReader::readComment()
-{
- Location commentBegin = this->current_ - 1;
- Char c = this->getNextChar();
+bool OurReader::readComment() {
+ Location commentBegin = current_ - 1;
+ Char c = getNextChar();
bool successful = false;
if (c == '*')
- successful = this->readCStyleComment();
+ successful = readCStyleComment();
else if (c == '/')
- successful = this->readCppStyleComment();
+ successful = readCppStyleComment();
if (!successful)
return false;
- if (this->collectComments_) {
+ if (collectComments_) {
CommentPlacement placement = commentBefore;
- if (this->lastValueEnd_ &&
- !containsNewLine(this->lastValueEnd_, commentBegin)) {
- if (c != '*' || !containsNewLine(commentBegin, this->current_))
+ if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, current_))
placement = commentAfterOnSameLine;
}
- this->addComment(commentBegin, this->current_, placement);
+ addComment(commentBegin, current_, placement);
}
return true;
}
-JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin,
- OurReader::Location end)
-{
+JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) {
JSONCPP_STRING normalized;
normalized.reserve(static_cast<size_t>(end - begin));
OurReader::Location current = begin;
@@ -1441,8 +1362,8 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin,
char c = *current++;
if (c == '\r') {
if (current != end && *current == '\n')
- // convert dos EOL
- ++current;
+ // convert dos EOL
+ ++current;
// convert Mac EOL
normalized += '\n';
} else {
@@ -1452,39 +1373,36 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin,
return normalized;
}
-void OurReader::addComment(Location begin, Location end,
- CommentPlacement placement)
-{
- assert(this->collectComments_);
+void
+OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
+ assert(collectComments_);
const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
- assert(this->lastValue_ != 0);
- this->lastValue_->setComment(normalized, placement);
+ assert(lastValue_ != 0);
+ lastValue_->setComment(normalized, placement);
} else {
- this->commentsBefore_ += normalized;
+ commentsBefore_ += normalized;
}
}
-bool OurReader::readCStyleComment()
-{
- while ((this->current_ + 1) < this->end_) {
- Char c = this->getNextChar();
- if (c == '*' && *this->current_ == '/')
+bool OurReader::readCStyleComment() {
+ while ((current_ + 1) < end_) {
+ Char c = getNextChar();
+ if (c == '*' && *current_ == '/')
break;
}
- return this->getNextChar() == '/';
+ return getNextChar() == '/';
}
-bool OurReader::readCppStyleComment()
-{
- while (this->current_ != this->end_) {
- Char c = this->getNextChar();
+bool OurReader::readCppStyleComment() {
+ while (current_ != end_) {
+ Char c = getNextChar();
if (c == '\n')
break;
if (c == '\r') {
// Consume DOS EOL. It will be normalized in addComment.
- if (this->current_ != this->end_ && *this->current_ == '\n')
- this->getNextChar();
+ if (current_ != end_ && *current_ == '\n')
+ getNextChar();
// Break on Moc OS 9 EOL.
break;
}
@@ -1492,156 +1410,150 @@ bool OurReader::readCppStyleComment()
return true;
}
-bool OurReader::readNumber(bool checkInf)
-{
- const char* p = this->current_;
- if (checkInf && p != this->end_ && *p == 'I') {
- this->current_ = ++p;
+bool OurReader::readNumber(bool checkInf) {
+ const char *p = current_;
+ if (checkInf && p != end_ && *p == 'I') {
+ current_ = ++p;
return false;
}
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
// fractional part
if (c == '.') {
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
}
// exponential part
if (c == 'e' || c == 'E') {
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
if (c == '+' || c == '-')
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (this->current_ = p) < this->end_ ? *p++ : '\0';
+ c = (current_ = p) < end_ ? *p++ : '\0';
}
return true;
}
-bool OurReader::readString()
-{
+bool OurReader::readString() {
Char c = 0;
- while (this->current_ != this->end_) {
- c = this->getNextChar();
+ while (current_ != end_) {
+ c = getNextChar();
if (c == '\\')
- this->getNextChar();
+ getNextChar();
else if (c == '"')
break;
}
return c == '"';
}
-bool OurReader::readStringSingleQuote()
-{
+
+bool OurReader::readStringSingleQuote() {
Char c = 0;
- while (this->current_ != this->end_) {
- c = this->getNextChar();
+ while (current_ != end_) {
+ c = getNextChar();
if (c == '\\')
- this->getNextChar();
+ getNextChar();
else if (c == '\'')
break;
}
return c == '\'';
}
-bool OurReader::readObject(Token& tokenStart)
-{
+bool OurReader::readObject(Token& tokenStart) {
Token tokenName;
JSONCPP_STRING name;
Value init(objectValue);
- this->currentValue().swapPayload(init);
- this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
- while (this->readToken(tokenName)) {
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ while (readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
- initialTokenOk = this->readToken(tokenName);
+ initialTokenOk = readToken(tokenName);
if (!initialTokenOk)
break;
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
return true;
name.clear();
if (tokenName.type_ == tokenString) {
- if (!this->decodeString(tokenName, name))
- return this->recoverFromError(tokenObjectEnd);
- } else if (tokenName.type_ == tokenNumber &&
- this->features_.allowNumericKeys_) {
+ if (!decodeString(tokenName, name))
+ return recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
Value numberName;
- if (!this->decodeNumber(tokenName, numberName))
- return this->recoverFromError(tokenObjectEnd);
+ if (!decodeNumber(tokenName, numberName))
+ return recoverFromError(tokenObjectEnd);
name = numberName.asString();
} else {
break;
}
Token colon;
- if (!this->readToken(colon) || colon.type_ != tokenMemberSeparator) {
- return this->addErrorAndRecover("Missing ':' after object member name",
- colon, tokenObjectEnd);
+ if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return addErrorAndRecover(
+ "Missing ':' after object member name", colon, tokenObjectEnd);
}
- if (name.length() >= (1U << 30))
- throwRuntimeError("keylength >= 2^30");
- if (this->features_.rejectDupKeys_ &&
- this->currentValue().isMember(name)) {
+ if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
+ if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
- return this->addErrorAndRecover(msg, tokenName, tokenObjectEnd);
+ return addErrorAndRecover(
+ msg, tokenName, tokenObjectEnd);
}
- Value& value = this->currentValue()[name];
- this->nodes_.push(&value);
- bool ok = this->readValue();
- this->nodes_.pop();
+ Value& value = currentValue()[name];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
if (!ok) // error already set
- return this->recoverFromError(tokenObjectEnd);
+ return recoverFromError(tokenObjectEnd);
Token comma;
- if (!this->readToken(comma) ||
+ if (!readToken(comma) ||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment)) {
- return this->addErrorAndRecover(
- "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ return addErrorAndRecover(
+ "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
}
bool finalizeTokenOk = true;
while (comma.type_ == tokenComment && finalizeTokenOk)
- finalizeTokenOk = this->readToken(comma);
+ finalizeTokenOk = readToken(comma);
if (comma.type_ == tokenObjectEnd)
return true;
}
- return this->addErrorAndRecover("Missing '}' or object member name",
- tokenName, tokenObjectEnd);
+ return addErrorAndRecover(
+ "Missing '}' or object member name", tokenName, tokenObjectEnd);
}
-bool OurReader::readArray(Token& tokenStart)
-{
+bool OurReader::readArray(Token& tokenStart) {
Value init(arrayValue);
- this->currentValue().swapPayload(init);
- this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
- this->skipSpaces();
- if (this->current_ != this->end_ && *this->current_ == ']') // empty array
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ skipSpaces();
+ if (current_ != end_ && *current_ == ']') // empty array
{
Token endArray;
- this->readToken(endArray);
+ readToken(endArray);
return true;
}
int index = 0;
for (;;) {
- Value& value = this->currentValue()[index++];
- this->nodes_.push(&value);
- bool ok = this->readValue();
- this->nodes_.pop();
+ Value& value = currentValue()[index++];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
if (!ok) // error already set
- return this->recoverFromError(tokenArrayEnd);
+ return recoverFromError(tokenArrayEnd);
Token token;
// Accept Comment after last item in the array.
- ok = this->readToken(token);
+ ok = readToken(token);
while (token.type_ == tokenComment && ok) {
- ok = this->readToken(token);
+ ok = readToken(token);
}
bool badTokenType =
- (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
if (!ok || badTokenType) {
- return this->addErrorAndRecover(
- "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ return addErrorAndRecover(
+ "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
}
if (token.type_ == tokenArrayEnd)
break;
@@ -1649,19 +1561,17 @@ bool OurReader::readArray(Token& tokenStart)
return true;
}
-bool OurReader::decodeNumber(Token& token)
-{
+bool OurReader::decodeNumber(Token& token) {
Value decoded;
- if (!this->decodeNumber(token, decoded))
+ if (!decodeNumber(token, decoded))
return false;
- this->currentValue().swapPayload(decoded);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
-bool OurReader::decodeNumber(Token& token, Value& decoded)
-{
+bool OurReader::decodeNumber(Token& token, Value& decoded) {
// Attempts to parse the number as an integer. If the number is
// larger than the maximum supported value of an integer then
// we decode the number as a double.
@@ -1669,17 +1579,16 @@ bool OurReader::decodeNumber(Token& token, Value& decoded)
bool isNegative = *current == '-';
if (isNegative)
++current;
- // TODO: Help the compiler do the div and mod at compile time or get rid of
- // them.
- Value::LargestUInt maxIntegerValue = isNegative
- ? Value::LargestUInt(Value::minLargestInt)
- : Value::maxLargestUInt;
+ // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+ Value::LargestUInt maxIntegerValue =
+ isNegative ? Value::LargestUInt(Value::minLargestInt)
+ : Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
Value::LargestUInt value = 0;
while (current < token.end_) {
Char c = *current++;
if (c < '0' || c > '9')
- return this->decodeDouble(token, decoded);
+ return decodeDouble(token, decoded);
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If
@@ -1688,7 +1597,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded)
// Otherwise treat this number as a double to avoid overflow.
if (value > threshold || current != token.end_ ||
digit > maxIntegerValue % 10) {
- return this->decodeDouble(token, decoded);
+ return decodeDouble(token, decoded);
}
}
value = value * 10 + digit;
@@ -1702,19 +1611,17 @@ bool OurReader::decodeNumber(Token& token, Value& decoded)
return true;
}
-bool OurReader::decodeDouble(Token& token)
-{
+bool OurReader::decodeDouble(Token& token) {
Value decoded;
- if (!this->decodeDouble(token, decoded))
+ if (!decodeDouble(token, decoded))
return false;
- this->currentValue().swapPayload(decoded);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
-bool OurReader::decodeDouble(Token& token, Value& decoded)
-{
+bool OurReader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
const int bufferSize = 32;
int count;
@@ -1722,7 +1629,7 @@ bool OurReader::decodeDouble(Token& token, Value& decoded)
// Sanity check to avoid buffer overflow exploits.
if (length < 0) {
- return this->addError("Unable to parse token length", token);
+ return addError("Unable to parse token length", token);
}
size_t const ulength = static_cast<size_t>(length);
@@ -1745,27 +1652,25 @@ bool OurReader::decodeDouble(Token& token, Value& decoded)
}
if (count != 1)
- return this->addError("'" + JSONCPP_STRING(token.start_, token.end_) +
- "' is not a number.",
- token);
+ return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
+ "' is not a number.",
+ token);
decoded = value;
return true;
}
-bool OurReader::decodeString(Token& token)
-{
+bool OurReader::decodeString(Token& token) {
JSONCPP_STRING decoded_string;
- if (!this->decodeString(token, decoded_string))
+ if (!decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
- this->currentValue().swapPayload(decoded);
- this->currentValue().setOffsetStart(token.start_ - this->begin_);
- this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
-bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded)
-{
+bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
@@ -1775,43 +1680,41 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded)
break;
else if (c == '\\') {
if (current == end)
- return this->addError("Empty escape sequence in string", token,
- current);
+ return addError("Empty escape sequence in string", token, current);
Char escape = *current++;
switch (escape) {
- case '"':
- decoded += '"';
- break;
- case '/':
- decoded += '/';
- break;
- case '\\':
- decoded += '\\';
- break;
- case 'b':
- decoded += '\b';
- break;
- case 'f':
- decoded += '\f';
- break;
- case 'n':
- decoded += '\n';
- break;
- case 'r':
- decoded += '\r';
- break;
- case 't':
- decoded += '\t';
- break;
- case 'u': {
- unsigned int unicode;
- if (!this->decodeUnicodeCodePoint(token, current, end, unicode))
- return false;
- decoded += codePointToUTF8(unicode);
- } break;
- default:
- return this->addError("Bad escape sequence in string", token,
- current);
+ case '"':
+ decoded += '"';
+ break;
+ case '/':
+ decoded += '/';
+ break;
+ case '\\':
+ decoded += '\\';
+ break;
+ case 'b':
+ decoded += '\b';
+ break;
+ case 'f':
+ decoded += '\f';
+ break;
+ case 'n':
+ decoded += '\n';
+ break;
+ case 'r':
+ decoded += '\r';
+ break;
+ case 't':
+ decoded += '\t';
+ break;
+ case 'u': {
+ unsigned int unicode;
+ if (!decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return addError("Bad escape sequence in string", token, current);
}
} else {
decoded += c;
@@ -1820,44 +1723,45 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded)
return true;
}
-bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current,
- Location end, unsigned int& unicode)
-{
+bool OurReader::decodeUnicodeCodePoint(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode) {
- unicode = 0; // Convince scanbuild this is always initialized before use.
- if (!this->decodeUnicodeEscapeSequence(token, current, end, unicode))
+ unicode = 0; // Convince clang-analyzer that this is initialized before use.
+ if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
return false;
if (unicode >= 0xD800 && unicode <= 0xDBFF) {
// surrogate pairs
if (end - current < 6)
- return this->addError(
- "additional six characters expected to parse unicode surrogate pair.",
- token, current);
+ return addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token,
+ current);
unsigned int surrogatePair;
if (*(current++) == '\\' && *(current++) == 'u') {
- if (this->decodeUnicodeEscapeSequence(token, current, end,
- surrogatePair)) {
- unicode =
- 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
return false;
} else
- return this->addError(
- "expecting another \\u token to begin the second half of "
- "a unicode surrogate pair",
- token, current);
+ return addError("expecting another \\u token to begin the second half of "
+ "a unicode surrogate pair",
+ token,
+ current);
}
return true;
}
-bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current,
- Location end,
- unsigned int& ret_unicode)
-{
+bool OurReader::decodeUnicodeEscapeSequence(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& ret_unicode) {
if (end - current < 4)
- return this->addError(
- "Bad unicode escape sequence in string: four digits expected.", token,
- current);
+ return addError(
+ "Bad unicode escape sequence in string: four digits expected.",
+ token,
+ current);
int unicode = 0;
for (int index = 0; index < 4; ++index) {
Char c = *current++;
@@ -1869,65 +1773,60 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current,
else if (c >= 'A' && c <= 'F')
unicode += c - 'A' + 10;
else
- return this->addError(
- "Bad unicode escape sequence in string: hexadecimal digit expected.",
- token, current);
+ return addError(
+ "Bad unicode escape sequence in string: hexadecimal digit expected.",
+ token,
+ current);
}
ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
-bool OurReader::addError(const JSONCPP_STRING& message, Token& token,
- Location extra)
-{
+bool
+OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = extra;
- this->errors_.push_back(info);
+ errors_.push_back(info);
return false;
}
-bool OurReader::recoverFromError(TokenType skipUntilToken)
-{
- size_t errorCount = this->errors_.size();
+bool OurReader::recoverFromError(TokenType skipUntilToken) {
+ size_t errorCount = errors_.size();
Token skip;
for (;;) {
- if (!this->readToken(skip))
- this->errors_.resize(errorCount); // discard errors caused by recovery
+ if (!readToken(skip))
+ errors_.resize(errorCount); // discard errors caused by recovery
if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
break;
}
- this->errors_.resize(errorCount);
+ errors_.resize(errorCount);
return false;
}
-bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message, Token& token,
- TokenType skipUntilToken)
-{
- this->addError(message, token);
- return this->recoverFromError(skipUntilToken);
+bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
+ Token& token,
+ TokenType skipUntilToken) {
+ addError(message, token);
+ return recoverFromError(skipUntilToken);
}
-Value& OurReader::currentValue()
-{
- return *(this->nodes_.top());
-}
+Value& OurReader::currentValue() { return *(nodes_.top()); }
-OurReader::Char OurReader::getNextChar()
-{
- if (this->current_ == this->end_)
+OurReader::Char OurReader::getNextChar() {
+ if (current_ == end_)
return 0;
- return *this->current_++;
+ return *current_++;
}
-void OurReader::getLocationLineAndColumn(Location location, int& line,
- int& column) const
-{
- Location current = this->begin_;
+void OurReader::getLocationLineAndColumn(Location location,
+ int& line,
+ int& column) const {
+ Location current = begin_;
Location lastLineStart = current;
line = 0;
- while (current < location && current != this->end_) {
+ while (current < location && current != end_) {
Char c = *current++;
if (c == '\r') {
if (*current == '\n')
@@ -1944,105 +1843,101 @@ void OurReader::getLocationLineAndColumn(Location location, int& line,
++line;
}
-JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const
-{
+JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
int line, column;
- this->getLocationLineAndColumn(location, line, column);
+ getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
return buffer;
}
-JSONCPP_STRING OurReader::getFormattedErrorMessages() const
-{
+JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
JSONCPP_STRING formattedMessage;
- for (Errors::const_iterator itError = this->errors_.begin();
- itError != this->errors_.end(); ++itError) {
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
const ErrorInfo& error = *itError;
formattedMessage +=
- "* " + this->getLocationLineAndColumn(error.token_.start_) + "\n";
+ "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
if (error.extra_)
- formattedMessage += "See " +
- this->getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ formattedMessage +=
+ "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
}
return formattedMessage;
}
-std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const
-{
+std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
std::vector<OurReader::StructuredError> allErrors;
- for (Errors::const_iterator itError = this->errors_.begin();
- itError != this->errors_.end(); ++itError) {
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
const ErrorInfo& error = *itError;
OurReader::StructuredError structured;
- structured.offset_start = error.token_.start_ - this->begin_;
- structured.offset_limit = error.token_.end_ - this->begin_;
+ structured.offset_start = error.token_.start_ - begin_;
+ structured.offset_limit = error.token_.end_ - begin_;
structured.message = error.message_;
allErrors.push_back(structured);
}
return allErrors;
}
-bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message)
-{
- ptrdiff_t length = this->end_ - this->begin_;
- if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
+ ptrdiff_t length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = this->begin_ + value.getOffsetStart();
- token.end_ = this->end_ + value.getOffsetLimit();
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = end_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = 0;
- this->errors_.push_back(info);
+ errors_.push_back(info);
return true;
}
-bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message,
- const Value& extra)
-{
- ptrdiff_t length = this->end_ - this->begin_;
- if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
- extra.getOffsetLimit() > length)
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
+ ptrdiff_t length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length
+ || extra.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = this->begin_ + value.getOffsetStart();
- token.end_ = this->begin_ + value.getOffsetLimit();
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = begin_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
- info.extra_ = this->begin_ + extra.getOffsetStart();
- this->errors_.push_back(info);
+ info.extra_ = begin_ + extra.getOffsetStart();
+ errors_.push_back(info);
return true;
}
-bool OurReader::good() const
-{
- return !this->errors_.size();
+bool OurReader::good() const {
+ return !errors_.size();
}
-class OurCharReader : public CharReader
-{
+
+class OurCharReader : public CharReader {
bool const collectComments_;
OurReader reader_;
-
public:
- OurCharReader(bool collectComments, OurFeatures const& features)
- : collectComments_(collectComments)
- , reader_(features)
- {
- }
- bool parse(char const* beginDoc, char const* endDoc, Value* root,
- JSONCPP_STRING* errs) JSONCPP_OVERRIDE
- {
- bool ok =
- this->reader_.parse(beginDoc, endDoc, *root, this->collectComments_);
+ OurCharReader(
+ bool collectComments,
+ OurFeatures const& features)
+ : collectComments_(collectComments)
+ , reader_(features)
+ {}
+ bool parse(
+ char const* beginDoc, char const* endDoc,
+ Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
+ bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
if (errs) {
- *errs = this->reader_.getFormattedErrorMessages();
+ *errs = reader_.getFormattedErrorMessages();
}
return ok;
}
@@ -2050,26 +1945,23 @@ public:
CharReaderBuilder::CharReaderBuilder()
{
- setDefaults(&this->settings_);
+ setDefaults(&settings_);
}
CharReaderBuilder::~CharReaderBuilder()
-{
-}
+{}
CharReader* CharReaderBuilder::newCharReader() const
{
- bool collectComments = this->settings_["collectComments"].asBool();
+ bool collectComments = settings_["collectComments"].asBool();
OurFeatures features = OurFeatures::all();
- features.allowComments_ = this->settings_["allowComments"].asBool();
- features.strictRoot_ = this->settings_["strictRoot"].asBool();
- features.allowDroppedNullPlaceholders_ =
- this->settings_["allowDroppedNullPlaceholders"].asBool();
- features.allowNumericKeys_ = this->settings_["allowNumericKeys"].asBool();
- features.allowSingleQuotes_ = this->settings_["allowSingleQuotes"].asBool();
- features.stackLimit_ = this->settings_["stackLimit"].asInt();
- features.failIfExtra_ = this->settings_["failIfExtra"].asBool();
- features.rejectDupKeys_ = this->settings_["rejectDupKeys"].asBool();
- features.allowSpecialFloats_ =
- this->settings_["allowSpecialFloats"].asBool();
+ features.allowComments_ = settings_["allowComments"].asBool();
+ features.strictRoot_ = settings_["strictRoot"].asBool();
+ features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
+ features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
+ features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
+ features.stackLimit_ = settings_["stackLimit"].asInt();
+ features.failIfExtra_ = settings_["failIfExtra"].asBool();
+ features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
+ features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
return new OurCharReader(collectComments, features);
}
static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
@@ -2089,29 +1981,28 @@ static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
bool CharReaderBuilder::validate(Json::Value* invalid) const
{
Json::Value my_invalid;
- if (!invalid)
- invalid = &my_invalid; // so we do not need to test for NULL
+ if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
Json::Value& inv = *invalid;
std::set<JSONCPP_STRING> valid_keys;
getValidReaderKeys(&valid_keys);
- Value::Members keys = this->settings_.getMemberNames();
+ Value::Members keys = settings_.getMemberNames();
size_t n = keys.size();
for (size_t i = 0; i < n; ++i) {
JSONCPP_STRING const& key = keys[i];
if (valid_keys.find(key) == valid_keys.end()) {
- inv[key] = this->settings_[key];
+ inv[key] = settings_[key];
}
}
return 0u == inv.size();
}
Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
{
- return this->settings_[key];
+ return settings_[key];
}
// static
void CharReaderBuilder::strictMode(Json::Value* settings)
{
- //! [CharReaderBuilderStrictMode]
+//! [CharReaderBuilderStrictMode]
(*settings)["allowComments"] = false;
(*settings)["strictRoot"] = true;
(*settings)["allowDroppedNullPlaceholders"] = false;
@@ -2121,12 +2012,12 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false;
- //! [CharReaderBuilderStrictMode]
+//! [CharReaderBuilderStrictMode]
}
// static
void CharReaderBuilder::setDefaults(Json::Value* settings)
{
- //! [CharReaderBuilderDefaults]
+//! [CharReaderBuilderDefaults]
(*settings)["collectComments"] = true;
(*settings)["allowComments"] = true;
(*settings)["strictRoot"] = false;
@@ -2137,14 +2028,15 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
(*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
- //! [CharReaderBuilderDefaults]
+//! [CharReaderBuilderDefaults]
}
//////////////////////////////////
// global functions
-bool parseFromStream(CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
- Value* root, JSONCPP_STRING* errs)
+bool parseFromStream(
+ CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
+ Value* root, JSONCPP_STRING* errs)
{
JSONCPP_OSTRINGSTREAM ssin;
ssin << sin.rdbuf();
@@ -2156,13 +2048,14 @@ bool parseFromStream(CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
return reader->parse(begin, end, root, errs);
}
-JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root)
-{
+JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
CharReaderBuilder b;
JSONCPP_STRING errs;
bool ok = parseFromStream(b, sin, &root, &errs);
if (!ok) {
- fprintf(stderr, "Error from reader: %s", errs.c_str());
+ fprintf(stderr,
+ "Error from reader: %s",
+ errs.c_str());
throwRuntimeError(errs);
}
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
index eadb1c375..f271e5731 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
@@ -1,25 +1,23 @@
// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at
-// http://jsoncpp.sourceforge.net/LICENSE
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
-# include <json/assertions.h>
-# include <json/value.h>
-# include <json/writer.h>
+#include <json/assertions.h>
+#include <json/value.h>
+#include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <math.h>
#include <sstream>
#include <utility>
-
-#include <assert.h>
-#include <math.h>
#include <string.h>
+#include <assert.h>
#ifdef JSON_USE_CPPTL
-# include <cpptl/conststring.h>
+#include <cpptl/conststring.h>
#endif
+#include <cstddef> // size_t
#include <algorithm> // min()
-#include <cstddef> // size_t
#define JSON_ASSERT_UNREACHABLE assert(false)
@@ -29,24 +27,24 @@ namespace Json {
// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
// 8 (instead of 4) as a bit of future-proofing.
#if defined(__ARMEL__)
-# define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
+#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#else
-# define ALIGNAS(byte_alignment)
+#define ALIGNAS(byte_alignment)
#endif
-// static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
-// const unsigned char& kNullRef = kNull[0];
-// const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
-// const Value& Value::nullRef = null;
+//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
+//const unsigned char& kNullRef = kNull[0];
+//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
+//const Value& Value::nullRef = null;
// static
Value const& Value::nullSingleton()
{
- static Value const nullStatic;
- return nullStatic;
+ static Value const nullStatic;
+ return nullStatic;
}
-// for backwards compatibility, we'll leave these global references around, but
-// DO NOT use them in JSONCPP library code any more!
+// for backwards compatibility, we'll leave these global references around, but DO NOT
+// use them in JSONCPP library code any more!
Value const& Value::null = Value::nullSingleton();
Value const& Value::nullRef = Value::nullSingleton();
@@ -68,29 +66,23 @@ const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
template <typename T, typename U>
-static inline bool InRange(double d, T min, U max)
-{
+static inline bool InRange(double d, T min, U max) {
// The casts can lose precision, but we are looking only for
// an approximate range. Might fail on edge cases though. ~cdunn
- // return d >= static_cast<double>(min) && d <= static_cast<double>(max);
+ //return d >= static_cast<double>(min) && d <= static_cast<double>(max);
return d >= min && d <= max;
}
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-static inline double integerToDouble(Json::UInt64 value)
-{
- return static_cast<double>(Int64(value / 2)) * 2.0 +
- static_cast<double>(Int64(value & 1));
+static inline double integerToDouble(Json::UInt64 value) {
+ return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
}
-template <typename T>
-static inline double integerToDouble(T value)
-{
+template <typename T> static inline double integerToDouble(T value) {
return static_cast<double>(value);
}
template <typename T, typename U>
-static inline bool InRange(double d, T min, U max)
-{
+static inline bool InRange(double d, T min, U max) {
return d >= integerToDouble(min) && d <= integerToDouble(max);
}
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
@@ -102,7 +94,8 @@ static inline bool InRange(double d, T min, U max)
* computed using strlen(value).
* @return Pointer on the duplicate instance of string.
*/
-static inline char* duplicateStringValue(const char* value, size_t length)
+static inline char* duplicateStringValue(const char* value,
+ size_t length)
{
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
@@ -111,8 +104,9 @@ static inline char* duplicateStringValue(const char* value, size_t length)
char* newString = static_cast<char*>(malloc(length + 1));
if (newString == NULL) {
- throwRuntimeError("in Json::Value::duplicateStringValue(): "
- "Failed to allocate string value buffer");
+ throwRuntimeError(
+ "in Json::Value::duplicateStringValue(): "
+ "Failed to allocate string value buffer");
}
memcpy(newString, value, length);
newString[length] = 0;
@@ -121,30 +115,30 @@ static inline char* duplicateStringValue(const char* value, size_t length)
/* Record the length as a prefix.
*/
-static inline char* duplicateAndPrefixStringValue(const char* value,
- unsigned int length)
+static inline char* duplicateAndPrefixStringValue(
+ const char* value,
+ unsigned int length)
{
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
- JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) -
- sizeof(unsigned) - 1U,
+ JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing");
- unsigned actualLength =
- length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
+ unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
char* newString = static_cast<char*>(malloc(actualLength));
if (newString == 0) {
- throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
- "Failed to allocate string value buffer");
+ throwRuntimeError(
+ "in Json::Value::duplicateAndPrefixStringValue(): "
+ "Failed to allocate string value buffer");
}
*reinterpret_cast<unsigned*>(newString) = length;
memcpy(newString + sizeof(unsigned), value, length);
- newString[actualLength - 1U] =
- 0; // to avoid buffer over-run accidents by users later
+ newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
return newString;
}
-inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
- unsigned* length, char const** value)
+inline static void decodePrefixedString(
+ bool isPrefixed, char const* prefixed,
+ unsigned* length, char const** value)
{
if (!isPrefixed) {
*length = static_cast<unsigned>(strlen(prefixed));
@@ -154,12 +148,10 @@ inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
*value = prefixed + sizeof(unsigned);
}
}
-/** Free the string duplicated by
- * duplicateStringValue()/duplicateAndPrefixStringValue().
+/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
*/
#if JSONCPP_USING_SECURE_MEMORY
-static inline void releasePrefixedStringValue(char* value)
-{
+static inline void releasePrefixedStringValue(char* value) {
unsigned length = 0;
char const* valueDecoded;
decodePrefixedString(true, value, &length, &valueDecoded);
@@ -167,20 +159,17 @@ static inline void releasePrefixedStringValue(char* value)
memset(value, 0, size);
free(value);
}
-static inline void releaseStringValue(char* value, unsigned length)
-{
+static inline void releaseStringValue(char* value, unsigned length) {
// length==0 => we allocated the strings memory
- size_t size = (length == 0) ? strlen(value) : length;
+ size_t size = (length==0) ? strlen(value) : length;
memset(value, 0, size);
free(value);
}
-#else // !JSONCPP_USING_SECURE_MEMORY
-static inline void releasePrefixedStringValue(char* value)
-{
+#else // !JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) {
free(value);
}
-static inline void releaseStringValue(char* value, unsigned)
-{
+static inline void releaseStringValue(char* value, unsigned) {
free(value);
}
#endif // JSONCPP_USING_SECURE_MEMORY
@@ -196,30 +185,26 @@ static inline void releaseStringValue(char* value, unsigned)
// //////////////////////////////////////////////////////////////////
#if !defined(JSON_IS_AMALGAMATION)
-# include "json_valueiterator.inl"
+#include "json_valueiterator.inl"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
Exception::Exception(JSONCPP_STRING const& msg)
: msg_(msg)
-{
-}
+{}
Exception::~Exception() JSONCPP_NOEXCEPT
-{
-}
+{}
char const* Exception::what() const JSONCPP_NOEXCEPT
{
- return this->msg_.c_str();
+ return msg_.c_str();
}
RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
: Exception(msg)
-{
-}
+{}
LogicError::LogicError(JSONCPP_STRING const& msg)
: Exception(msg)
-{
-}
+{}
JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
{
throw RuntimeError(msg);
@@ -237,29 +222,25 @@ JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
-Value::CommentInfo::CommentInfo()
- : comment_(0)
-{
-}
+Value::CommentInfo::CommentInfo() : comment_(0)
+{}
-Value::CommentInfo::~CommentInfo()
-{
- if (this->comment_)
- releaseStringValue(this->comment_, 0u);
+Value::CommentInfo::~CommentInfo() {
+ if (comment_)
+ releaseStringValue(comment_, 0u);
}
-void Value::CommentInfo::setComment(const char* text, size_t len)
-{
- if (this->comment_) {
- releaseStringValue(this->comment_, 0u);
- this->comment_ = 0;
+void Value::CommentInfo::setComment(const char* text, size_t len) {
+ if (comment_) {
+ releaseStringValue(comment_, 0u);
+ comment_ = 0;
}
JSON_ASSERT(text != 0);
JSON_ASSERT_MESSAGE(
- text[0] == '\0' || text[0] == '/',
- "in Json::Value::setComment(): Comments must start with /");
+ text[0] == '\0' || text[0] == '/',
+ "in Json::Value::setComment(): Comments must start with /");
// It seems that /**/ style comments are acceptable as well.
- this->comment_ = duplicateStringValue(text, len);
+ comment_ = duplicateStringValue(text, len);
}
// //////////////////////////////////////////////////////////////////
@@ -273,130 +254,91 @@ void Value::CommentInfo::setComment(const char* text, size_t len)
// Notes: policy_ indicates if the string was allocated when
// a string is stored.
-Value::CZString::CZString(ArrayIndex aindex)
- : cstr_(0)
- , index_(aindex)
-{
-}
+Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
-Value::CZString::CZString(char const* str, unsigned ulength,
- DuplicationPolicy allocate)
- : cstr_(str)
-{
+Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
+ : cstr_(str) {
// allocate != duplicate
- this->storage_.policy_ = allocate & 0x3;
- this->storage_.length_ = ulength & 0x3FFFFFFF;
+ storage_.policy_ = allocate & 0x3;
+ storage_.length_ = ulength & 0x3FFFFFFF;
}
-Value::CZString::CZString(const CZString& other)
-{
- this->cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
- ? duplicateStringValue(other.cstr_, other.storage_.length_)
- : other.cstr_);
- this->storage_.policy_ =
- static_cast<unsigned>(
- other.cstr_ ? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
- noDuplication
- ? noDuplication
- : duplicate)
- : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
- 3U;
- this->storage_.length_ = other.storage_.length_;
+Value::CZString::CZString(const CZString& other) {
+ cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
+ ? duplicateStringValue(other.cstr_, other.storage_.length_)
+ : other.cstr_);
+ storage_.policy_ = static_cast<unsigned>(other.cstr_
+ ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
+ ? noDuplication : duplicate)
+ : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
+ storage_.length_ = other.storage_.length_;
}
#if JSON_HAS_RVALUE_REFERENCES
Value::CZString::CZString(CZString&& other)
- : cstr_(other.cstr_)
- , index_(other.index_)
-{
+ : cstr_(other.cstr_), index_(other.index_) {
other.cstr_ = nullptr;
}
#endif
-Value::CZString::~CZString()
-{
- if (this->cstr_ && this->storage_.policy_ == duplicate) {
- releaseStringValue(const_cast<char*>(this->cstr_),
- this->storage_.length_ +
- 1u); //+1 for null terminating character for sake of
- //completeness but not actually necessary
+Value::CZString::~CZString() {
+ if (cstr_ && storage_.policy_ == duplicate) {
+ releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
}
}
-void Value::CZString::swap(CZString& other)
-{
- std::swap(this->cstr_, other.cstr_);
- std::swap(this->index_, other.index_);
+void Value::CZString::swap(CZString& other) {
+ std::swap(cstr_, other.cstr_);
+ std::swap(index_, other.index_);
}
-Value::CZString& Value::CZString::operator=(const CZString& other)
-{
- this->cstr_ = other.cstr_;
- this->index_ = other.index_;
+Value::CZString& Value::CZString::operator=(const CZString& other) {
+ cstr_ = other.cstr_;
+ index_ = other.index_;
return *this;
}
#if JSON_HAS_RVALUE_REFERENCES
-Value::CZString& Value::CZString::operator=(CZString&& other)
-{
- this->cstr_ = other.cstr_;
- this->index_ = other.index_;
+Value::CZString& Value::CZString::operator=(CZString&& other) {
+ cstr_ = other.cstr_;
+ index_ = other.index_;
other.cstr_ = nullptr;
return *this;
}
#endif
-bool Value::CZString::operator<(const CZString& other) const
-{
- if (!this->cstr_)
- return this->index_ < other.index_;
- // return strcmp(cstr_, other.cstr_) < 0;
+bool Value::CZString::operator<(const CZString& other) const {
+ if (!cstr_) return index_ < other.index_;
+ //return strcmp(cstr_, other.cstr_) < 0;
// Assume both are strings.
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
unsigned min_len = std::min<unsigned>(this_len, other_len);
JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, min_len);
- if (comp < 0)
- return true;
- if (comp > 0)
- return false;
+ if (comp < 0) return true;
+ if (comp > 0) return false;
return (this_len < other_len);
}
-bool Value::CZString::operator==(const CZString& other) const
-{
- if (!this->cstr_)
- return this->index_ == other.index_;
- // return strcmp(cstr_, other.cstr_) == 0;
+bool Value::CZString::operator==(const CZString& other) const {
+ if (!cstr_) return index_ == other.index_;
+ //return strcmp(cstr_, other.cstr_) == 0;
// Assume both are strings.
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
- if (this_len != other_len)
- return false;
+ if (this_len != other_len) return false;
JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, this_len);
return comp == 0;
}
-ArrayIndex Value::CZString::index() const
-{
- return this->index_;
-}
+ArrayIndex Value::CZString::index() const { return index_; }
-// const char* Value::CZString::c_str() const { return cstr_; }
-const char* Value::CZString::data() const
-{
- return this->cstr_;
-}
-unsigned Value::CZString::length() const
-{
- return this->storage_.length_;
-}
-bool Value::CZString::isStaticString() const
-{
- return this->storage_.policy_ == noDuplication;
-}
+//const char* Value::CZString::c_str() const { return cstr_; }
+const char* Value::CZString::data() const { return cstr_; }
+unsigned Value::CZString::length() const { return storage_.length_; }
+bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
@@ -410,238 +352,210 @@ bool Value::CZString::isStaticString() const
* memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator.
*/
-Value::Value(ValueType vtype)
-{
+Value::Value(ValueType vtype) {
static char const emptyString[] = "";
- this->initBasic(vtype);
+ initBasic(vtype);
switch (vtype) {
- case nullValue:
- break;
- case intValue:
- case uintValue:
- this->value_.int_ = 0;
- break;
- case realValue:
- this->value_.real_ = 0.0;
- break;
- case stringValue:
- // allocated_ == false, so this is safe.
- this->value_.string_ =
- const_cast<char*>(static_cast<char const*>(emptyString));
- break;
- case arrayValue:
- case objectValue:
- this->value_.map_ = new ObjectValues();
- break;
- case booleanValue:
- this->value_.bool_ = false;
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
+ case nullValue:
+ break;
+ case intValue:
+ case uintValue:
+ value_.int_ = 0;
+ break;
+ case realValue:
+ value_.real_ = 0.0;
+ break;
+ case stringValue:
+ // allocated_ == false, so this is safe.
+ value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
+ break;
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues();
+ break;
+ case booleanValue:
+ value_.bool_ = false;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
}
-Value::Value(Int value)
-{
- this->initBasic(intValue);
- this->value_.int_ = value;
+Value::Value(Int value) {
+ initBasic(intValue);
+ value_.int_ = value;
}
-Value::Value(UInt value)
-{
- this->initBasic(uintValue);
- this->value_.uint_ = value;
+Value::Value(UInt value) {
+ initBasic(uintValue);
+ value_.uint_ = value;
}
#if defined(JSON_HAS_INT64)
-Value::Value(Int64 value)
-{
- this->initBasic(intValue);
- this->value_.int_ = value;
+Value::Value(Int64 value) {
+ initBasic(intValue);
+ value_.int_ = value;
}
-Value::Value(UInt64 value)
-{
- this->initBasic(uintValue);
- this->value_.uint_ = value;
+Value::Value(UInt64 value) {
+ initBasic(uintValue);
+ value_.uint_ = value;
}
#endif // defined(JSON_HAS_INT64)
-Value::Value(double value)
-{
- this->initBasic(realValue);
- this->value_.real_ = value;
+Value::Value(double value) {
+ initBasic(realValue);
+ value_.real_ = value;
}
-Value::Value(const char* value)
-{
- this->initBasic(stringValue, true);
+Value::Value(const char* value) {
+ initBasic(stringValue, true);
JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
- this->value_.string_ =
- duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
+ value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
}
-Value::Value(const char* beginValue, const char* endValue)
-{
- this->initBasic(stringValue, true);
- this->value_.string_ = duplicateAndPrefixStringValue(
- beginValue, static_cast<unsigned>(endValue - beginValue));
+Value::Value(const char* beginValue, const char* endValue) {
+ initBasic(stringValue, true);
+ value_.string_ =
+ duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
}
-Value::Value(const JSONCPP_STRING& value)
-{
- this->initBasic(stringValue, true);
- this->value_.string_ = duplicateAndPrefixStringValue(
- value.data(), static_cast<unsigned>(value.length()));
+Value::Value(const JSONCPP_STRING& value) {
+ initBasic(stringValue, true);
+ value_.string_ =
+ duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
}
-Value::Value(const StaticString& value)
-{
- this->initBasic(stringValue);
- this->value_.string_ = const_cast<char*>(value.c_str());
+Value::Value(const StaticString& value) {
+ initBasic(stringValue);
+ value_.string_ = const_cast<char*>(value.c_str());
}
#ifdef JSON_USE_CPPTL
-Value::Value(const CppTL::ConstString& value)
-{
+Value::Value(const CppTL::ConstString& value) {
initBasic(stringValue, true);
- value_.string_ = duplicateAndPrefixStringValue(
- value, static_cast<unsigned>(value.length()));
+ value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
}
#endif
-Value::Value(bool value)
-{
- this->initBasic(booleanValue);
- this->value_.bool_ = value;
+Value::Value(bool value) {
+ initBasic(booleanValue);
+ value_.bool_ = value;
}
Value::Value(Value const& other)
- : type_(other.type_)
- , allocated_(false)
- , comments_(0)
- , start_(other.start_)
- , limit_(other.limit_)
-{
- switch (this->type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- this->value_ = other.value_;
- break;
- case stringValue:
- if (other.value_.string_ && other.allocated_) {
- unsigned len;
- char const* str;
- decodePrefixedString(other.allocated_, other.value_.string_, &len,
- &str);
- this->value_.string_ = duplicateAndPrefixStringValue(str, len);
- this->allocated_ = true;
- } else {
- this->value_.string_ = other.value_.string_;
- this->allocated_ = false;
- }
- break;
- case arrayValue:
- case objectValue:
- this->value_.map_ = new ObjectValues(*other.value_.map_);
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
+ : type_(other.type_), allocated_(false)
+ ,
+ comments_(0), start_(other.start_), limit_(other.limit_)
+{
+ switch (type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ value_ = other.value_;
+ break;
+ case stringValue:
+ if (other.value_.string_ && other.allocated_) {
+ unsigned len;
+ char const* str;
+ decodePrefixedString(other.allocated_, other.value_.string_,
+ &len, &str);
+ value_.string_ = duplicateAndPrefixStringValue(str, len);
+ allocated_ = true;
+ } else {
+ value_.string_ = other.value_.string_;
+ allocated_ = false;
+ }
+ break;
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues(*other.value_.map_);
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
if (other.comments_) {
- this->comments_ = new CommentInfo[numberOfCommentPlacement];
+ comments_ = new CommentInfo[numberOfCommentPlacement];
for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
const CommentInfo& otherComment = other.comments_[comment];
if (otherComment.comment_)
- this->comments_[comment].setComment(otherComment.comment_,
- strlen(otherComment.comment_));
+ comments_[comment].setComment(
+ otherComment.comment_, strlen(otherComment.comment_));
}
}
}
#if JSON_HAS_RVALUE_REFERENCES
// Move constructor
-Value::Value(Value&& other)
-{
- this->initBasic(nullValue);
- this->swap(other);
+Value::Value(Value&& other) {
+ initBasic(nullValue);
+ swap(other);
}
#endif
-Value::~Value()
-{
- switch (this->type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- break;
- case stringValue:
- if (this->allocated_)
- releasePrefixedStringValue(this->value_.string_);
- break;
- case arrayValue:
- case objectValue:
- delete this->value_.map_;
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
+Value::~Value() {
+ switch (type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue:
+ if (allocated_)
+ releasePrefixedStringValue(value_.string_);
+ break;
+ case arrayValue:
+ case objectValue:
+ delete value_.map_;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
- delete[] this->comments_;
+ delete[] comments_;
- this->value_.uint_ = 0;
+ value_.uint_ = 0;
}
-Value& Value::operator=(Value other)
-{
- this->swap(other);
+Value& Value::operator=(Value other) {
+ swap(other);
return *this;
}
-void Value::swapPayload(Value& other)
-{
- ValueType temp = this->type_;
- this->type_ = other.type_;
+void Value::swapPayload(Value& other) {
+ ValueType temp = type_;
+ type_ = other.type_;
other.type_ = temp;
- std::swap(this->value_, other.value_);
- int temp2 = this->allocated_;
- this->allocated_ = other.allocated_;
+ std::swap(value_, other.value_);
+ int temp2 = allocated_;
+ allocated_ = other.allocated_;
other.allocated_ = temp2 & 0x1;
}
-void Value::copyPayload(const Value& other)
-{
- this->type_ = other.type_;
- this->value_ = other.value_;
- this->allocated_ = other.allocated_;
+void Value::copyPayload(const Value& other) {
+ type_ = other.type_;
+ value_ = other.value_;
+ allocated_ = other.allocated_;
}
-void Value::swap(Value& other)
-{
- this->swapPayload(other);
- std::swap(this->comments_, other.comments_);
- std::swap(this->start_, other.start_);
- std::swap(this->limit_, other.limit_);
+void Value::swap(Value& other) {
+ swapPayload(other);
+ std::swap(comments_, other.comments_);
+ std::swap(start_, other.start_);
+ std::swap(limit_, other.limit_);
}
-void Value::copy(const Value& other)
-{
- this->copyPayload(other);
- this->comments_ = other.comments_;
- this->start_ = other.start_;
- this->limit_ = other.limit_;
+void Value::copy(const Value& other) {
+ copyPayload(other);
+ comments_ = other.comments_;
+ start_ = other.start_;
+ limit_ = other.limit_;
}
-ValueType Value::type() const
-{
- return this->type_;
-}
+ValueType Value::type() const { return type_; }
-int Value::compare(const Value& other) const
-{
+int Value::compare(const Value& other) const {
if (*this < other)
return -1;
if (*this > other)
@@ -649,568 +563,509 @@ int Value::compare(const Value& other) const
return 0;
}
-bool Value::operator<(const Value& other) const
-{
- int typeDelta = this->type_ - other.type_;
+bool Value::operator<(const Value& other) const {
+ int typeDelta = type_ - other.type_;
if (typeDelta)
return typeDelta < 0 ? true : false;
- switch (this->type_) {
- case nullValue:
- return false;
- case intValue:
- return this->value_.int_ < other.value_.int_;
- case uintValue:
- return this->value_.uint_ < other.value_.uint_;
- case realValue:
- return this->value_.real_ < other.value_.real_;
- case booleanValue:
- return this->value_.bool_ < other.value_.bool_;
- case stringValue: {
- if ((this->value_.string_ == 0) || (other.value_.string_ == 0)) {
- if (other.value_.string_)
- return true;
- else
- return false;
- }
- unsigned this_len;
- unsigned other_len;
- char const* this_str;
- char const* other_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
- &this_str);
- decodePrefixedString(other.allocated_, other.value_.string_, &other_len,
- &other_str);
- unsigned min_len = std::min<unsigned>(this_len, other_len);
- JSON_ASSERT(this_str && other_str);
- int comp = memcmp(this_str, other_str, min_len);
- if (comp < 0)
- return true;
- if (comp > 0)
- return false;
- return (this_len < other_len);
- }
- case arrayValue:
- case objectValue: {
- int delta = int(this->value_.map_->size() - other.value_.map_->size());
- if (delta)
- return delta < 0;
- return (*this->value_.map_) < (*other.value_.map_);
+ switch (type_) {
+ case nullValue:
+ return false;
+ case intValue:
+ return value_.int_ < other.value_.int_;
+ case uintValue:
+ return value_.uint_ < other.value_.uint_;
+ case realValue:
+ return value_.real_ < other.value_.real_;
+ case booleanValue:
+ return value_.bool_ < other.value_.bool_;
+ case stringValue:
+ {
+ if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+ if (other.value_.string_) return true;
+ else return false;
}
- default:
- JSON_ASSERT_UNREACHABLE;
+ unsigned this_len;
+ unsigned other_len;
+ char const* this_str;
+ char const* other_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+ unsigned min_len = std::min<unsigned>(this_len, other_len);
+ JSON_ASSERT(this_str && other_str);
+ int comp = memcmp(this_str, other_str, min_len);
+ if (comp < 0) return true;
+ if (comp > 0) return false;
+ return (this_len < other_len);
+ }
+ case arrayValue:
+ case objectValue: {
+ int delta = int(value_.map_->size() - other.value_.map_->size());
+ if (delta)
+ return delta < 0;
+ return (*value_.map_) < (*other.value_.map_);
+ }
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
return false; // unreachable
}
-bool Value::operator<=(const Value& other) const
-{
- return !(other < *this);
-}
+bool Value::operator<=(const Value& other) const { return !(other < *this); }
-bool Value::operator>=(const Value& other) const
-{
- return !(*this < other);
-}
+bool Value::operator>=(const Value& other) const { return !(*this < other); }
-bool Value::operator>(const Value& other) const
-{
- return other < *this;
-}
+bool Value::operator>(const Value& other) const { return other < *this; }
-bool Value::operator==(const Value& other) const
-{
+bool Value::operator==(const Value& other) const {
// if ( type_ != other.type_ )
// GCC 2.95.3 says:
// attempt to take address of bit-field structure member `Json::Value::type_'
// Beats me, but a temp solves the problem.
int temp = other.type_;
- if (this->type_ != temp)
+ if (type_ != temp)
return false;
- switch (this->type_) {
- case nullValue:
- return true;
- case intValue:
- return this->value_.int_ == other.value_.int_;
- case uintValue:
- return this->value_.uint_ == other.value_.uint_;
- case realValue:
- return this->value_.real_ == other.value_.real_;
- case booleanValue:
- return this->value_.bool_ == other.value_.bool_;
- case stringValue: {
- if ((this->value_.string_ == 0) || (other.value_.string_ == 0)) {
- return (this->value_.string_ == other.value_.string_);
- }
- unsigned this_len;
- unsigned other_len;
- char const* this_str;
- char const* other_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
- &this_str);
- decodePrefixedString(other.allocated_, other.value_.string_, &other_len,
- &other_str);
- if (this_len != other_len)
- return false;
- JSON_ASSERT(this_str && other_str);
- int comp = memcmp(this_str, other_str, this_len);
- return comp == 0;
+ switch (type_) {
+ case nullValue:
+ return true;
+ case intValue:
+ return value_.int_ == other.value_.int_;
+ case uintValue:
+ return value_.uint_ == other.value_.uint_;
+ case realValue:
+ return value_.real_ == other.value_.real_;
+ case booleanValue:
+ return value_.bool_ == other.value_.bool_;
+ case stringValue:
+ {
+ if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+ return (value_.string_ == other.value_.string_);
}
- case arrayValue:
- case objectValue:
- return this->value_.map_->size() == other.value_.map_->size() &&
- (*this->value_.map_) == (*other.value_.map_);
- default:
- JSON_ASSERT_UNREACHABLE;
+ unsigned this_len;
+ unsigned other_len;
+ char const* this_str;
+ char const* other_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+ if (this_len != other_len) return false;
+ JSON_ASSERT(this_str && other_str);
+ int comp = memcmp(this_str, other_str, this_len);
+ return comp == 0;
+ }
+ case arrayValue:
+ case objectValue:
+ return value_.map_->size() == other.value_.map_->size() &&
+ (*value_.map_) == (*other.value_.map_);
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
return false; // unreachable
}
-bool Value::operator!=(const Value& other) const
-{
- return !(*this == other);
-}
+bool Value::operator!=(const Value& other) const { return !(*this == other); }
-const char* Value::asCString() const
-{
+const char* Value::asCString() const {
JSON_ASSERT_MESSAGE(type_ == stringValue,
"in Json::Value::asCString(): requires stringValue");
- if (this->value_.string_ == 0)
- return 0;
+ if (value_.string_ == 0) return 0;
unsigned this_len;
char const* this_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
- &this_str);
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
return this_str;
}
#if JSONCPP_USING_SECURE_MEMORY
-unsigned Value::getCStringLength() const
-{
+unsigned Value::getCStringLength() const {
JSON_ASSERT_MESSAGE(type_ == stringValue,
- "in Json::Value::asCString(): requires stringValue");
- if (value_.string_ == 0)
- return 0;
+ "in Json::Value::asCString(): requires stringValue");
+ if (value_.string_ == 0) return 0;
unsigned this_len;
char const* this_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
- &this_str);
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
return this_len;
}
#endif
-bool Value::getString(char const** str, char const** cend) const
-{
- if (this->type_ != stringValue)
- return false;
- if (this->value_.string_ == 0)
- return false;
+bool Value::getString(char const** str, char const** cend) const {
+ if (type_ != stringValue) return false;
+ if (value_.string_ == 0) return false;
unsigned length;
decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
*cend = *str + length;
return true;
}
-JSONCPP_STRING Value::asString() const
-{
- switch (this->type_) {
- case nullValue:
- return "";
- case stringValue: {
- if (this->value_.string_ == 0)
- return "";
- unsigned this_len;
- char const* this_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
- &this_str);
- return JSONCPP_STRING(this_str, this_len);
- }
- case booleanValue:
- return this->value_.bool_ ? "true" : "false";
- case intValue:
- return valueToString(this->value_.int_);
- case uintValue:
- return valueToString(this->value_.uint_);
- case realValue:
- return valueToString(this->value_.real_);
- default:
- JSON_FAIL_MESSAGE("Type is not convertible to string");
+JSONCPP_STRING Value::asString() const {
+ switch (type_) {
+ case nullValue:
+ return "";
+ case stringValue:
+ {
+ if (value_.string_ == 0) return "";
+ unsigned this_len;
+ char const* this_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ return JSONCPP_STRING(this_str, this_len);
+ }
+ case booleanValue:
+ return value_.bool_ ? "true" : "false";
+ case intValue:
+ return valueToString(value_.int_);
+ case uintValue:
+ return valueToString(value_.uint_);
+ case realValue:
+ return valueToString(value_.real_);
+ default:
+ JSON_FAIL_MESSAGE("Type is not convertible to string");
}
}
#ifdef JSON_USE_CPPTL
-CppTL::ConstString Value::asConstString() const
-{
+CppTL::ConstString Value::asConstString() const {
unsigned len;
char const* str;
- decodePrefixedString(allocated_, value_.string_, &len, &str);
+ decodePrefixedString(allocated_, value_.string_,
+ &len, &str);
return CppTL::ConstString(str, len);
}
#endif
-Value::Int Value::asInt() const
-{
- switch (this->type_) {
- case intValue:
- JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
- return Int(this->value_.int_);
- case uintValue:
- JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
- return Int(this->value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
- "double out of Int range");
- return Int(this->value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return this->value_.bool_ ? 1 : 0;
- default:
- break;
+Value::Int Value::asInt() const {
+ switch (type_) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
+ return Int(value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
+ return Int(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
+ "double out of Int range");
+ return Int(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to Int.");
}
-Value::UInt Value::asUInt() const
-{
- switch (this->type_) {
- case intValue:
- JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
- return UInt(this->value_.int_);
- case uintValue:
- JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
- return UInt(this->value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
- "double out of UInt range");
- return UInt(this->value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return this->value_.bool_ ? 1 : 0;
- default:
- break;
+Value::UInt Value::asUInt() const {
+ switch (type_) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
+ return UInt(value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
+ return UInt(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
+ "double out of UInt range");
+ return UInt(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
}
#if defined(JSON_HAS_INT64)
-Value::Int64 Value::asInt64() const
-{
- switch (this->type_) {
- case intValue:
- return Int64(this->value_.int_);
- case uintValue:
- JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
- return Int64(this->value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
- "double out of Int64 range");
- return Int64(this->value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return this->value_.bool_ ? 1 : 0;
- default:
- break;
+Value::Int64 Value::asInt64() const {
+ switch (type_) {
+ case intValue:
+ return Int64(value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
+ return Int64(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
+ "double out of Int64 range");
+ return Int64(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
}
-Value::UInt64 Value::asUInt64() const
-{
- switch (this->type_) {
- case intValue:
- JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
- return UInt64(this->value_.int_);
- case uintValue:
- return UInt64(this->value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
- "double out of UInt64 range");
- return UInt64(this->value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return this->value_.bool_ ? 1 : 0;
- default:
- break;
+Value::UInt64 Value::asUInt64() const {
+ switch (type_) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
+ return UInt64(value_.int_);
+ case uintValue:
+ return UInt64(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
+ "double out of UInt64 range");
+ return UInt64(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
}
#endif // if defined(JSON_HAS_INT64)
-LargestInt Value::asLargestInt() const
-{
+LargestInt Value::asLargestInt() const {
#if defined(JSON_NO_INT64)
return asInt();
#else
- return this->asInt64();
+ return asInt64();
#endif
}
-LargestUInt Value::asLargestUInt() const
-{
+LargestUInt Value::asLargestUInt() const {
#if defined(JSON_NO_INT64)
return asUInt();
#else
- return this->asUInt64();
+ return asUInt64();
#endif
}
-double Value::asDouble() const
-{
- switch (this->type_) {
- case intValue:
- return static_cast<double>(this->value_.int_);
- case uintValue:
+double Value::asDouble() const {
+ switch (type_) {
+ case intValue:
+ return static_cast<double>(value_.int_);
+ case uintValue:
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return static_cast<double>(this->value_.uint_);
+ return static_cast<double>(value_.uint_);
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return integerToDouble(value_.uint_);
+ return integerToDouble(value_.uint_);
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- case realValue:
- return this->value_.real_;
- case nullValue:
- return 0.0;
- case booleanValue:
- return this->value_.bool_ ? 1.0 : 0.0;
- default:
- break;
+ case realValue:
+ return value_.real_;
+ case nullValue:
+ return 0.0;
+ case booleanValue:
+ return value_.bool_ ? 1.0 : 0.0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to double.");
}
-float Value::asFloat() const
-{
- switch (this->type_) {
- case intValue:
- return static_cast<float>(this->value_.int_);
- case uintValue:
+float Value::asFloat() const {
+ switch (type_) {
+ case intValue:
+ return static_cast<float>(value_.int_);
+ case uintValue:
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return static_cast<float>(this->value_.uint_);
+ return static_cast<float>(value_.uint_);
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- // This can fail (silently?) if the value is bigger than MAX_FLOAT.
- return static_cast<float>(integerToDouble(value_.uint_));
+ // This can fail (silently?) if the value is bigger than MAX_FLOAT.
+ return static_cast<float>(integerToDouble(value_.uint_));
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- case realValue:
- return static_cast<float>(this->value_.real_);
- case nullValue:
- return 0.0;
- case booleanValue:
- return this->value_.bool_ ? 1.0f : 0.0f;
- default:
- break;
+ case realValue:
+ return static_cast<float>(value_.real_);
+ case nullValue:
+ return 0.0;
+ case booleanValue:
+ return value_.bool_ ? 1.0f : 0.0f;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to float.");
}
-bool Value::asBool() const
-{
- switch (this->type_) {
- case booleanValue:
- return this->value_.bool_;
- case nullValue:
- return false;
- case intValue:
- return this->value_.int_ ? true : false;
- case uintValue:
- return this->value_.uint_ ? true : false;
- case realValue:
- // This is kind of strange. Not recommended.
- return (this->value_.real_ != 0.0) ? true : false;
- default:
- break;
+bool Value::asBool() const {
+ switch (type_) {
+ case booleanValue:
+ return value_.bool_;
+ case nullValue:
+ return false;
+ case intValue:
+ return value_.int_ ? true : false;
+ case uintValue:
+ return value_.uint_ ? true : false;
+ case realValue:
+ // This is kind of strange. Not recommended.
+ return (value_.real_ != 0.0) ? true : false;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to bool.");
}
-bool Value::isConvertibleTo(ValueType other) const
-{
+bool Value::isConvertibleTo(ValueType other) const {
switch (other) {
- case nullValue:
- return (this->isNumeric() && this->asDouble() == 0.0) ||
- (this->type_ == booleanValue && this->value_.bool_ == false) ||
- (this->type_ == stringValue && this->asString().empty()) ||
- (this->type_ == arrayValue && this->value_.map_->size() == 0) ||
- (this->type_ == objectValue && this->value_.map_->size() == 0) ||
- this->type_ == nullValue;
- case intValue:
- return this->isInt() ||
- (this->type_ == realValue &&
- InRange(this->value_.real_, minInt, maxInt)) ||
- this->type_ == booleanValue || this->type_ == nullValue;
- case uintValue:
- return this->isUInt() ||
- (this->type_ == realValue &&
- InRange(this->value_.real_, 0, maxUInt)) ||
- this->type_ == booleanValue || this->type_ == nullValue;
- case realValue:
- return this->isNumeric() || this->type_ == booleanValue ||
- this->type_ == nullValue;
- case booleanValue:
- return this->isNumeric() || this->type_ == booleanValue ||
- this->type_ == nullValue;
- case stringValue:
- return this->isNumeric() || this->type_ == booleanValue ||
- this->type_ == stringValue || this->type_ == nullValue;
- case arrayValue:
- return this->type_ == arrayValue || this->type_ == nullValue;
- case objectValue:
- return this->type_ == objectValue || this->type_ == nullValue;
+ case nullValue:
+ return (isNumeric() && asDouble() == 0.0) ||
+ (type_ == booleanValue && value_.bool_ == false) ||
+ (type_ == stringValue && asString().empty()) ||
+ (type_ == arrayValue && value_.map_->size() == 0) ||
+ (type_ == objectValue && value_.map_->size() == 0) ||
+ type_ == nullValue;
+ case intValue:
+ return isInt() ||
+ (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
+ type_ == booleanValue || type_ == nullValue;
+ case uintValue:
+ return isUInt() ||
+ (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
+ type_ == booleanValue || type_ == nullValue;
+ case realValue:
+ return isNumeric() || type_ == booleanValue || type_ == nullValue;
+ case booleanValue:
+ return isNumeric() || type_ == booleanValue || type_ == nullValue;
+ case stringValue:
+ return isNumeric() || type_ == booleanValue || type_ == stringValue ||
+ type_ == nullValue;
+ case arrayValue:
+ return type_ == arrayValue || type_ == nullValue;
+ case objectValue:
+ return type_ == objectValue || type_ == nullValue;
}
JSON_ASSERT_UNREACHABLE;
return false;
}
/// Number of values in array or object
-ArrayIndex Value::size() const
-{
- switch (this->type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- case stringValue:
- return 0;
- case arrayValue: // size of the array is highest index + 1
- if (!this->value_.map_->empty()) {
- ObjectValues::const_iterator itLast = this->value_.map_->end();
- --itLast;
- return (*itLast).first.index() + 1;
- }
- return 0;
- case objectValue:
- return ArrayIndex(this->value_.map_->size());
+ArrayIndex Value::size() const {
+ switch (type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ case stringValue:
+ return 0;
+ case arrayValue: // size of the array is highest index + 1
+ if (!value_.map_->empty()) {
+ ObjectValues::const_iterator itLast = value_.map_->end();
+ --itLast;
+ return (*itLast).first.index() + 1;
+ }
+ return 0;
+ case objectValue:
+ return ArrayIndex(value_.map_->size());
}
JSON_ASSERT_UNREACHABLE;
return 0; // unreachable;
}
-bool Value::empty() const
-{
- if (this->isNull() || this->isArray() || this->isObject())
- return this->size() == 0u;
+bool Value::empty() const {
+ if (isNull() || isArray() || isObject())
+ return size() == 0u;
else
return false;
}
-bool Value::operator!() const
-{
- return this->isNull();
-}
+bool Value::operator!() const { return isNull(); }
-void Value::clear()
-{
+void Value::clear() {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
- type_ == objectValue,
+ type_ == objectValue,
"in Json::Value::clear(): requires complex value");
- this->start_ = 0;
- this->limit_ = 0;
- switch (this->type_) {
- case arrayValue:
- case objectValue:
- this->value_.map_->clear();
- break;
- default:
- break;
+ start_ = 0;
+ limit_ = 0;
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ value_.map_->clear();
+ break;
+ default:
+ break;
}
}
-void Value::resize(ArrayIndex newSize)
-{
+void Value::resize(ArrayIndex newSize) {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
"in Json::Value::resize(): requires arrayValue");
- if (this->type_ == nullValue)
+ if (type_ == nullValue)
*this = Value(arrayValue);
- ArrayIndex oldSize = this->size();
+ ArrayIndex oldSize = size();
if (newSize == 0)
- this->clear();
+ clear();
else if (newSize > oldSize)
(*this)[newSize - 1];
else {
for (ArrayIndex index = newSize; index < oldSize; ++index) {
- this->value_.map_->erase(index);
+ value_.map_->erase(index);
}
JSON_ASSERT(size() == newSize);
}
}
-Value& Value::operator[](ArrayIndex index)
-{
+Value& Value::operator[](ArrayIndex index) {
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == arrayValue,
- "in Json::Value::operator[](ArrayIndex): requires arrayValue");
- if (this->type_ == nullValue)
+ type_ == nullValue || type_ == arrayValue,
+ "in Json::Value::operator[](ArrayIndex): requires arrayValue");
+ if (type_ == nullValue)
*this = Value(arrayValue);
CZString key(index);
- ObjectValues::iterator it = this->value_.map_->lower_bound(key);
- if (it != this->value_.map_->end() && (*it).first == key)
+ ObjectValues::iterator it = value_.map_->lower_bound(key);
+ if (it != value_.map_->end() && (*it).first == key)
return (*it).second;
ObjectValues::value_type defaultValue(key, nullSingleton());
- it = this->value_.map_->insert(it, defaultValue);
+ it = value_.map_->insert(it, defaultValue);
return (*it).second;
}
-Value& Value::operator[](int index)
-{
+Value& Value::operator[](int index) {
JSON_ASSERT_MESSAGE(
- index >= 0,
- "in Json::Value::operator[](int index): index cannot be negative");
+ index >= 0,
+ "in Json::Value::operator[](int index): index cannot be negative");
return (*this)[ArrayIndex(index)];
}
-const Value& Value::operator[](ArrayIndex index) const
-{
+const Value& Value::operator[](ArrayIndex index) const {
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == arrayValue,
- "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
- if (this->type_ == nullValue)
+ type_ == nullValue || type_ == arrayValue,
+ "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
+ if (type_ == nullValue)
return nullSingleton();
CZString key(index);
- ObjectValues::const_iterator it = this->value_.map_->find(key);
- if (it == this->value_.map_->end())
+ ObjectValues::const_iterator it = value_.map_->find(key);
+ if (it == value_.map_->end())
return nullSingleton();
return (*it).second;
}
-const Value& Value::operator[](int index) const
-{
+const Value& Value::operator[](int index) const {
JSON_ASSERT_MESSAGE(
- index >= 0,
- "in Json::Value::operator[](int index) const: index cannot be negative");
+ index >= 0,
+ "in Json::Value::operator[](int index) const: index cannot be negative");
return (*this)[ArrayIndex(index)];
}
-void Value::initBasic(ValueType vtype, bool allocated)
-{
- this->type_ = vtype;
- this->allocated_ = allocated;
- this->comments_ = 0;
- this->start_ = 0;
- this->limit_ = 0;
+void Value::initBasic(ValueType vtype, bool allocated) {
+ type_ = vtype;
+ allocated_ = allocated;
+ comments_ = 0;
+ start_ = 0;
+ limit_ = 0;
}
// Access an object value by name, create a null member if it does not exist.
// @pre Type of '*this' is object or null.
// @param key is null-terminated.
-Value& Value::resolveReference(const char* key)
-{
+Value& Value::resolveReference(const char* key) {
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
- "in Json::Value::resolveReference(): requires objectValue");
- if (this->type_ == nullValue)
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::resolveReference(): requires objectValue");
+ if (type_ == nullValue)
*this = Value(objectValue);
- CZString actualKey(key, static_cast<unsigned>(strlen(key)),
- CZString::noDuplication); // NOTE!
- ObjectValues::iterator it = this->value_.map_->lower_bound(actualKey);
- if (it != this->value_.map_->end() && (*it).first == actualKey)
+ CZString actualKey(
+ key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
+ ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+ if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
- it = this->value_.map_->insert(it, defaultValue);
+ it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
}
@@ -1219,223 +1074,198 @@ Value& Value::resolveReference(const char* key)
Value& Value::resolveReference(char const* key, char const* cend)
{
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
- "in Json::Value::resolveReference(key, end): requires objectValue");
- if (this->type_ == nullValue)
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::resolveReference(key, end): requires objectValue");
+ if (type_ == nullValue)
*this = Value(objectValue);
- CZString actualKey(key, static_cast<unsigned>(cend - key),
- CZString::duplicateOnCopy);
- ObjectValues::iterator it = this->value_.map_->lower_bound(actualKey);
- if (it != this->value_.map_->end() && (*it).first == actualKey)
+ CZString actualKey(
+ key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
+ ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+ if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
- it = this->value_.map_->insert(it, defaultValue);
+ it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
}
-Value Value::get(ArrayIndex index, const Value& defaultValue) const
-{
+Value Value::get(ArrayIndex index, const Value& defaultValue) const {
const Value* value = &((*this)[index]);
return value == &nullSingleton() ? defaultValue : *value;
}
-bool Value::isValidIndex(ArrayIndex index) const
-{
- return index < this->size();
-}
+bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
Value const* Value::find(char const* key, char const* cend) const
{
- JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
- "in Json::Value::find(key, end, found): requires "
- "objectValue or nullValue");
- if (this->type_ == nullValue)
- return NULL;
- CZString actualKey(key, static_cast<unsigned>(cend - key),
- CZString::noDuplication);
- ObjectValues::const_iterator it = this->value_.map_->find(actualKey);
- if (it == this->value_.map_->end())
- return NULL;
+ JSON_ASSERT_MESSAGE(
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::find(key, end, found): requires objectValue or nullValue");
+ if (type_ == nullValue) return NULL;
+ CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
+ ObjectValues::const_iterator it = value_.map_->find(actualKey);
+ if (it == value_.map_->end()) return NULL;
return &(*it).second;
}
const Value& Value::operator[](const char* key) const
{
- Value const* found = this->find(key, key + strlen(key));
- if (!found)
- return nullSingleton();
+ Value const* found = find(key, key + strlen(key));
+ if (!found) return nullSingleton();
return *found;
}
Value const& Value::operator[](JSONCPP_STRING const& key) const
{
- Value const* found = this->find(key.data(), key.data() + key.length());
- if (!found)
- return nullSingleton();
+ Value const* found = find(key.data(), key.data() + key.length());
+ if (!found) return nullSingleton();
return *found;
}
-Value& Value::operator[](const char* key)
-{
- return this->resolveReference(key, key + strlen(key));
+Value& Value::operator[](const char* key) {
+ return resolveReference(key, key + strlen(key));
}
-Value& Value::operator[](const JSONCPP_STRING& key)
-{
- return this->resolveReference(key.data(), key.data() + key.length());
+Value& Value::operator[](const JSONCPP_STRING& key) {
+ return resolveReference(key.data(), key.data() + key.length());
}
-Value& Value::operator[](const StaticString& key)
-{
- return this->resolveReference(key.c_str());
+Value& Value::operator[](const StaticString& key) {
+ return resolveReference(key.c_str());
}
#ifdef JSON_USE_CPPTL
-Value& Value::operator[](const CppTL::ConstString& key)
-{
+Value& Value::operator[](const CppTL::ConstString& key) {
return resolveReference(key.c_str(), key.end_c_str());
}
Value const& Value::operator[](CppTL::ConstString const& key) const
{
Value const* found = find(key.c_str(), key.end_c_str());
- if (!found)
- return nullSingleton();
+ if (!found) return nullSingleton();
return *found;
}
#endif
-Value& Value::append(const Value& value)
-{
- return (*this)[this->size()] = value;
-}
+Value& Value::append(const Value& value) { return (*this)[size()] = value; }
#if JSON_HAS_RVALUE_REFERENCES
-Value& Value::append(Value&& value)
-{
- return (*this)[this->size()] = value;
-}
+ Value& Value::append(Value&& value) { return (*this)[size()] = value; }
#endif
-Value Value::get(char const* key, char const* cend,
- Value const& defaultValue) const
+Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
{
- Value const* found = this->find(key, cend);
+ Value const* found = find(key, cend);
return !found ? defaultValue : *found;
}
Value Value::get(char const* key, Value const& defaultValue) const
{
- return this->get(key, key + strlen(key), defaultValue);
+ return get(key, key + strlen(key), defaultValue);
}
Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
{
- return this->get(key.data(), key.data() + key.length(), defaultValue);
+ return get(key.data(), key.data() + key.length(), defaultValue);
}
+
bool Value::removeMember(const char* key, const char* cend, Value* removed)
{
- if (this->type_ != objectValue) {
+ if (type_ != objectValue) {
return false;
}
- CZString actualKey(key, static_cast<unsigned>(cend - key),
- CZString::noDuplication);
- ObjectValues::iterator it = this->value_.map_->find(actualKey);
- if (it == this->value_.map_->end())
+ CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
+ ObjectValues::iterator it = value_.map_->find(actualKey);
+ if (it == value_.map_->end())
return false;
*removed = it->second;
- this->value_.map_->erase(it);
+ value_.map_->erase(it);
return true;
}
bool Value::removeMember(const char* key, Value* removed)
{
- return this->removeMember(key, key + strlen(key), removed);
+ return removeMember(key, key + strlen(key), removed);
}
bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
{
- return this->removeMember(key.data(), key.data() + key.length(), removed);
+ return removeMember(key.data(), key.data() + key.length(), removed);
}
Value Value::removeMember(const char* key)
{
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue");
- if (this->type_ == nullValue)
+ if (type_ == nullValue)
return nullSingleton();
- Value removed; // null
- this->removeMember(key, key + strlen(key), &removed);
+ Value removed; // null
+ removeMember(key, key + strlen(key), &removed);
return removed; // still null if removeMember() did nothing
}
Value Value::removeMember(const JSONCPP_STRING& key)
{
- return this->removeMember(key.c_str());
+ return removeMember(key.c_str());
}
-bool Value::removeIndex(ArrayIndex index, Value* removed)
-{
- if (this->type_ != arrayValue) {
+bool Value::removeIndex(ArrayIndex index, Value* removed) {
+ if (type_ != arrayValue) {
return false;
}
CZString key(index);
- ObjectValues::iterator it = this->value_.map_->find(key);
- if (it == this->value_.map_->end()) {
+ ObjectValues::iterator it = value_.map_->find(key);
+ if (it == value_.map_->end()) {
return false;
}
*removed = it->second;
- ArrayIndex oldSize = this->size();
+ ArrayIndex oldSize = size();
// shift left all items left, into the place of the "removed"
- for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
+ for (ArrayIndex i = index; i < (oldSize - 1); ++i){
CZString keey(i);
- (*this->value_.map_)[keey] = (*this)[i + 1];
+ (*value_.map_)[keey] = (*this)[i + 1];
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
- ObjectValues::iterator itLast = this->value_.map_->find(keyLast);
- this->value_.map_->erase(itLast);
+ ObjectValues::iterator itLast = value_.map_->find(keyLast);
+ value_.map_->erase(itLast);
return true;
}
#ifdef JSON_USE_CPPTL
Value Value::get(const CppTL::ConstString& key,
- const Value& defaultValue) const
-{
+ const Value& defaultValue) const {
return get(key.c_str(), key.end_c_str(), defaultValue);
}
#endif
bool Value::isMember(char const* key, char const* cend) const
{
- Value const* value = this->find(key, cend);
+ Value const* value = find(key, cend);
return NULL != value;
}
bool Value::isMember(char const* key) const
{
- return this->isMember(key, key + strlen(key));
+ return isMember(key, key + strlen(key));
}
bool Value::isMember(JSONCPP_STRING const& key) const
{
- return this->isMember(key.data(), key.data() + key.length());
+ return isMember(key.data(), key.data() + key.length());
}
#ifdef JSON_USE_CPPTL
-bool Value::isMember(const CppTL::ConstString& key) const
-{
+bool Value::isMember(const CppTL::ConstString& key) const {
return isMember(key.c_str(), key.end_c_str());
}
#endif
-Value::Members Value::getMemberNames() const
-{
+Value::Members Value::getMemberNames() const {
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
- "in Json::Value::getMemberNames(), value must be objectValue");
- if (this->type_ == nullValue)
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::getMemberNames(), value must be objectValue");
+ if (type_ == nullValue)
return Value::Members();
Members members;
- members.reserve(this->value_.map_->size());
- ObjectValues::const_iterator it = this->value_.map_->begin();
- ObjectValues::const_iterator itEnd = this->value_.map_->end();
+ members.reserve(value_.map_->size());
+ ObjectValues::const_iterator it = value_.map_->begin();
+ ObjectValues::const_iterator itEnd = value_.map_->end();
for (; it != itEnd; ++it) {
- members.push_back(
- JSONCPP_STRING((*it).first.data(), (*it).first.length()));
+ members.push_back(JSONCPP_STRING((*it).first.data(),
+ (*it).first.length()));
}
return members;
}
@@ -1447,8 +1277,8 @@ Value::Members Value::getMemberNames() const
// if ( type_ == objectValue )
// {
// return CppTL::Enum::any( CppTL::Enum::transform(
-// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>()
-// ), MemberNamesTransform() ) );
+// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+// MemberNamesTransform() ) );
// }
// return EnumMemberNames();
//}
@@ -1465,114 +1295,99 @@ Value::Members Value::getMemberNames() const
//
//# endif
-static bool IsIntegral(double d)
-{
+static bool IsIntegral(double d) {
double integral_part;
return modf(d, &integral_part) == 0.0;
}
-bool Value::isNull() const
-{
- return this->type_ == nullValue;
-}
+bool Value::isNull() const { return type_ == nullValue; }
-bool Value::isBool() const
-{
- return this->type_ == booleanValue;
-}
+bool Value::isBool() const { return type_ == booleanValue; }
-bool Value::isInt() const
-{
- switch (this->type_) {
- case intValue:
+bool Value::isInt() const {
+ switch (type_) {
+ case intValue:
#if defined(JSON_HAS_INT64)
- return this->value_.int_ >= minInt && this->value_.int_ <= maxInt;
+ return value_.int_ >= minInt && value_.int_ <= maxInt;
#else
- return true;
+ return true;
#endif
- case uintValue:
- return this->value_.uint_ <= UInt(maxInt);
- case realValue:
- return this->value_.real_ >= minInt && this->value_.real_ <= maxInt &&
- IsIntegral(this->value_.real_);
- default:
- break;
+ case uintValue:
+ return value_.uint_ <= UInt(maxInt);
+ case realValue:
+ return value_.real_ >= minInt && value_.real_ <= maxInt &&
+ IsIntegral(value_.real_);
+ default:
+ break;
}
return false;
}
-bool Value::isUInt() const
-{
- switch (this->type_) {
- case intValue:
+bool Value::isUInt() const {
+ switch (type_) {
+ case intValue:
#if defined(JSON_HAS_INT64)
- return this->value_.int_ >= 0 &&
- LargestUInt(this->value_.int_) <= LargestUInt(maxUInt);
+ return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
#else
- return value_.int_ >= 0;
+ return value_.int_ >= 0;
#endif
- case uintValue:
+ case uintValue:
#if defined(JSON_HAS_INT64)
- return this->value_.uint_ <= maxUInt;
+ return value_.uint_ <= maxUInt;
#else
- return true;
+ return true;
#endif
- case realValue:
- return this->value_.real_ >= 0 && this->value_.real_ <= maxUInt &&
- IsIntegral(this->value_.real_);
- default:
- break;
+ case realValue:
+ return value_.real_ >= 0 && value_.real_ <= maxUInt &&
+ IsIntegral(value_.real_);
+ default:
+ break;
}
return false;
}
-bool Value::isInt64() const
-{
+bool Value::isInt64() const {
#if defined(JSON_HAS_INT64)
- switch (this->type_) {
- case intValue:
- return true;
- case uintValue:
- return this->value_.uint_ <= UInt64(maxInt64);
- case realValue:
- // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
- // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
- // require the value to be strictly less than the limit.
- return this->value_.real_ >= double(minInt64) &&
- this->value_.real_ < double(maxInt64) &&
- IsIntegral(this->value_.real_);
- default:
- break;
+ switch (type_) {
+ case intValue:
+ return true;
+ case uintValue:
+ return value_.uint_ <= UInt64(maxInt64);
+ case realValue:
+ // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
+ // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
+ // require the value to be strictly less than the limit.
+ return value_.real_ >= double(minInt64) &&
+ value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
+ default:
+ break;
}
#endif // JSON_HAS_INT64
return false;
}
-bool Value::isUInt64() const
-{
+bool Value::isUInt64() const {
#if defined(JSON_HAS_INT64)
- switch (this->type_) {
- case intValue:
- return this->value_.int_ >= 0;
- case uintValue:
- return true;
- case realValue:
- // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
- // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
- // require the value to be strictly less than the limit.
- return this->value_.real_ >= 0 &&
- this->value_.real_ < maxUInt64AsDouble &&
- IsIntegral(this->value_.real_);
- default:
- break;
+ switch (type_) {
+ case intValue:
+ return value_.int_ >= 0;
+ case uintValue:
+ return true;
+ case realValue:
+ // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+ // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+ // require the value to be strictly less than the limit.
+ return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
+ IsIntegral(value_.real_);
+ default:
+ break;
}
#endif // JSON_HAS_INT64
return false;
}
-bool Value::isIntegral() const
-{
- switch (this->type_) {
+bool Value::isIntegral() const {
+ switch (type_) {
case intValue:
case uintValue:
return true;
@@ -1581,12 +1396,9 @@ bool Value::isIntegral() const
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
// require the value to be strictly less than the limit.
- return this->value_.real_ >= double(minInt64) &&
- this->value_.real_ < maxUInt64AsDouble &&
- IsIntegral(this->value_.real_);
+ return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
#else
- return value_.real_ >= minInt && value_.real_ <= maxUInt &&
- IsIntegral(value_.real_);
+ return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
#endif // JSON_HAS_INT64
default:
break;
@@ -1594,89 +1406,53 @@ bool Value::isIntegral() const
return false;
}
-bool Value::isDouble() const
-{
- return this->type_ == intValue || this->type_ == uintValue ||
- this->type_ == realValue;
-}
+bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
-bool Value::isNumeric() const
-{
- return this->isDouble();
-}
+bool Value::isNumeric() const { return isDouble(); }
-bool Value::isString() const
-{
- return this->type_ == stringValue;
-}
+bool Value::isString() const { return type_ == stringValue; }
-bool Value::isArray() const
-{
- return this->type_ == arrayValue;
-}
+bool Value::isArray() const { return type_ == arrayValue; }
-bool Value::isObject() const
-{
- return this->type_ == objectValue;
-}
+bool Value::isObject() const { return type_ == objectValue; }
-void Value::setComment(const char* comment, size_t len,
- CommentPlacement placement)
-{
- if (!this->comments_)
- this->comments_ = new CommentInfo[numberOfCommentPlacement];
- if ((len > 0) && (comment[len - 1] == '\n')) {
+void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
+ if (!comments_)
+ comments_ = new CommentInfo[numberOfCommentPlacement];
+ if ((len > 0) && (comment[len-1] == '\n')) {
// Always discard trailing newline, to aid indentation.
len -= 1;
}
- this->comments_[placement].setComment(comment, len);
+ comments_[placement].setComment(comment, len);
}
-void Value::setComment(const char* comment, CommentPlacement placement)
-{
- this->setComment(comment, strlen(comment), placement);
+void Value::setComment(const char* comment, CommentPlacement placement) {
+ setComment(comment, strlen(comment), placement);
}
-void Value::setComment(const JSONCPP_STRING& comment,
- CommentPlacement placement)
-{
- this->setComment(comment.c_str(), comment.length(), placement);
+void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
+ setComment(comment.c_str(), comment.length(), placement);
}
-bool Value::hasComment(CommentPlacement placement) const
-{
- return this->comments_ != 0 && this->comments_[placement].comment_ != 0;
+bool Value::hasComment(CommentPlacement placement) const {
+ return comments_ != 0 && comments_[placement].comment_ != 0;
}
-JSONCPP_STRING Value::getComment(CommentPlacement placement) const
-{
- if (this->hasComment(placement))
- return this->comments_[placement].comment_;
+JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
+ if (hasComment(placement))
+ return comments_[placement].comment_;
return "";
}
-void Value::setOffsetStart(ptrdiff_t start)
-{
- this->start_ = start;
-}
+void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
-void Value::setOffsetLimit(ptrdiff_t limit)
-{
- this->limit_ = limit;
-}
+void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
-ptrdiff_t Value::getOffsetStart() const
-{
- return this->start_;
-}
+ptrdiff_t Value::getOffsetStart() const { return start_; }
-ptrdiff_t Value::getOffsetLimit() const
-{
- return this->limit_;
-}
+ptrdiff_t Value::getOffsetLimit() const { return limit_; }
-JSONCPP_STRING Value::toStyledString() const
-{
+JSONCPP_STRING Value::toStyledString() const {
StreamWriterBuilder builder;
JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : "";
@@ -1686,58 +1462,54 @@ JSONCPP_STRING Value::toStyledString() const
return out;
}
-Value::const_iterator Value::begin() const
-{
- switch (this->type_) {
- case arrayValue:
- case objectValue:
- if (this->value_.map_)
- return const_iterator(this->value_.map_->begin());
- break;
- default:
- break;
+Value::const_iterator Value::begin() const {
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return const_iterator(value_.map_->begin());
+ break;
+ default:
+ break;
}
return const_iterator();
}
-Value::const_iterator Value::end() const
-{
- switch (this->type_) {
- case arrayValue:
- case objectValue:
- if (this->value_.map_)
- return const_iterator(this->value_.map_->end());
- break;
- default:
- break;
+Value::const_iterator Value::end() const {
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return const_iterator(value_.map_->end());
+ break;
+ default:
+ break;
}
return const_iterator();
}
-Value::iterator Value::begin()
-{
- switch (this->type_) {
- case arrayValue:
- case objectValue:
- if (this->value_.map_)
- return iterator(this->value_.map_->begin());
- break;
- default:
- break;
+Value::iterator Value::begin() {
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return iterator(value_.map_->begin());
+ break;
+ default:
+ break;
}
return iterator();
}
-Value::iterator Value::end()
-{
- switch (this->type_) {
- case arrayValue:
- case objectValue:
- if (this->value_.map_)
- return iterator(this->value_.map_->end());
- break;
- default:
- break;
+Value::iterator Value::end() {
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return iterator(value_.map_->end());
+ break;
+ default:
+ break;
}
return iterator();
}
@@ -1745,41 +1517,26 @@ Value::iterator Value::end()
// class PathArgument
// //////////////////////////////////////////////////////////////////
-PathArgument::PathArgument()
- : key_()
- , index_()
- , kind_(kindNone)
-{
-}
+PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
PathArgument::PathArgument(ArrayIndex index)
- : key_()
- , index_(index)
- , kind_(kindIndex)
-{
-}
+ : key_(), index_(index), kind_(kindIndex) {}
PathArgument::PathArgument(const char* key)
- : key_(key)
- , index_()
- , kind_(kindKey)
-{
-}
+ : key_(key), index_(), kind_(kindKey) {}
PathArgument::PathArgument(const JSONCPP_STRING& key)
- : key_(key.c_str())
- , index_()
- , kind_(kindKey)
-{
-}
+ : key_(key.c_str()), index_(), kind_(kindKey) {}
// class Path
// //////////////////////////////////////////////////////////////////
-Path::Path(const JSONCPP_STRING& path, const PathArgument& a1,
- const PathArgument& a2, const PathArgument& a3,
- const PathArgument& a4, const PathArgument& a5)
-{
+Path::Path(const JSONCPP_STRING& path,
+ const PathArgument& a1,
+ const PathArgument& a2,
+ const PathArgument& a3,
+ const PathArgument& a4,
+ const PathArgument& a5) {
InArgs in;
in.reserve(5);
in.push_back(&a1);
@@ -1787,11 +1544,10 @@ Path::Path(const JSONCPP_STRING& path, const PathArgument& a1,
in.push_back(&a3);
in.push_back(&a4);
in.push_back(&a5);
- this->makePath(path, in);
+ makePath(path, in);
}
-void Path::makePath(const JSONCPP_STRING& path, const InArgs& in)
-{
+void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
const char* current = path.c_str();
const char* end = current + path.length();
InArgs::const_iterator itInArg = in.begin();
@@ -1799,17 +1555,17 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in)
if (*current == '[') {
++current;
if (*current == '%')
- this->addPathInArg(path, in, itInArg, PathArgument::kindIndex);
+ addPathInArg(path, in, itInArg, PathArgument::kindIndex);
else {
ArrayIndex index = 0;
for (; current != end && *current >= '0' && *current <= '9'; ++current)
index = index * 10 + ArrayIndex(*current - '0');
- this->args_.push_back(index);
+ args_.push_back(index);
}
if (current == end || *++current != ']')
- this->invalidPath(path, int(current - path.c_str()));
+ invalidPath(path, int(current - path.c_str()));
} else if (*current == '%') {
- this->addPathInArg(path, in, itInArg, PathArgument::kindKey);
+ addPathInArg(path, in, itInArg, PathArgument::kindKey);
++current;
} else if (*current == '.' || *current == ']') {
++current;
@@ -1817,34 +1573,31 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in)
const char* beginName = current;
while (current != end && !strchr("[.", *current))
++current;
- this->args_.push_back(JSONCPP_STRING(beginName, current));
+ args_.push_back(JSONCPP_STRING(beginName, current));
}
}
}
-void Path::addPathInArg(const JSONCPP_STRING& /*path*/, const InArgs& in,
+void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
+ const InArgs& in,
InArgs::const_iterator& itInArg,
- PathArgument::Kind kind)
-{
+ PathArgument::Kind kind) {
if (itInArg == in.end()) {
// Error: missing argument %d
} else if ((*itInArg)->kind_ != kind) {
// Error: bad argument type
} else {
- this->args_.push_back(**itInArg++);
+ args_.push_back(**itInArg++);
}
}
-void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/)
-{
+void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
// Error: invalid path.
}
-const Value& Path::resolve(const Value& root) const
-{
+const Value& Path::resolve(const Value& root) const {
const Value* node = &root;
- for (Args::const_iterator it = this->args_.begin(); it != this->args_.end();
- ++it) {
+ for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
const PathArgument& arg = *it;
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
@@ -1868,11 +1621,9 @@ const Value& Path::resolve(const Value& root) const
return *node;
}
-Value Path::resolve(const Value& root, const Value& defaultValue) const
-{
+Value Path::resolve(const Value& root, const Value& defaultValue) const {
const Value* node = &root;
- for (Args::const_iterator it = this->args_.begin(); it != this->args_.end();
- ++it) {
+ for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
const PathArgument& arg = *it;
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_))
@@ -1889,11 +1640,9 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const
return *node;
}
-Value& Path::make(Value& root) const
-{
+Value& Path::make(Value& root) const {
Value* node = &root;
- for (Args::const_iterator it = this->args_.begin(); it != this->args_.end();
- ++it) {
+ for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
const PathArgument& arg = *it;
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray()) {
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
index 803cfab01..fc8650598 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
@@ -1,115 +1,111 @@
// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at
-// http://jsoncpp.sourceforge.net/LICENSE
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
-# include <json/writer.h>
-
-# include "json_tool.h"
+#include <json/writer.h>
+#include "json_tool.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <cassert>
-#include <cstdio>
-#include <cstring>
#include <iomanip>
#include <memory>
-#include <set>
#include <sstream>
#include <utility>
+#include <set>
+#include <cassert>
+#include <cstring>
+#include <cstdio>
-#if defined(_MSC_VER) && _MSC_VER >= 1200 && \
- _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
-# include <float.h>
-# define isfinite _finite
-#elif defined(__sun) && defined(__SVR4) // Solaris
-# if !defined(isfinite)
-# include <ieeefp.h>
-# define isfinite finite
-# endif
+#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
+#include <float.h>
+#define isfinite _finite
+#elif defined(__sun) && defined(__SVR4) //Solaris
+#if !defined(isfinite)
+#include <ieeefp.h>
+#define isfinite finite
+#endif
#elif defined(_AIX)
-# if !defined(isfinite)
-# include <math.h>
-# define isfinite finite
-# endif
+#if !defined(isfinite)
+#include <math.h>
+#define isfinite finite
+#endif
#elif defined(__hpux)
-# if !defined(isfinite) && !defined(__GNUC__)
-# if defined(__ia64) && !defined(finite)
-# define isfinite(x) \
- ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
-# else
-# include <math.h>
-# define isfinite finite
-# endif
-# endif
+#if !defined(isfinite) && !defined(__GNUC__)
+#if defined(__ia64) && !defined(finite)
+#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
+ _Isfinitef(x) : _IsFinite(x)))
#else
-# include <cmath>
-# if !(defined(__QNXNTO__)) // QNX already defines isfinite
-# define isfinite std::isfinite
-# endif
+#include <math.h>
+#define isfinite finite
+#endif
+#endif
+#else
+#include <cmath>
+#if !(defined(__QNXNTO__)) // QNX already defines isfinite
+#define isfinite std::isfinite
+#endif
#endif
#if defined(_MSC_VER)
-# if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && \
- _MSC_VER >= 1500 // VC++ 9.0 and above
-# define snprintf sprintf_s
-# elif _MSC_VER >= 1900 // VC++ 14.0 and above
-# define snprintf std::snprintf
-# else
-# define snprintf _snprintf
-# endif
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
+#define snprintf _snprintf
+#endif
#elif defined(__ANDROID__) || defined(__QNXNTO__)
-# define snprintf snprintf
+#define snprintf snprintf
#elif __cplusplus >= 201103L
-# if !defined(__MINGW32__) && !defined(__CYGWIN__)
-# define snprintf std::snprintf
-# endif
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
+#define snprintf std::snprintf
+#endif
#endif
-#if defined(__BORLANDC__)
-# include <float.h>
-# define isfinite _finite
-# define snprintf _snprintf
+#if defined(__BORLANDC__)
+#include <float.h>
+#define isfinite _finite
+#define snprintf _snprintf
#endif
// Solaris
#if defined(__sun)
-# include <ieeefp.h>
-# if !defined(isfinite)
-# define isfinite finite
-# endif
+# include <ieeefp.h>
+# if !defined(isfinite)
+# define isfinite finite
+# endif
#endif
// AIX
#if defined(_AIX)
-# if !defined(isfinite)
-# define isfinite finite
-# endif
+# if !defined(isfinite)
+# define isfinite finite
+# endif
#endif
// HP-UX
#if defined(__hpux)
-# if !defined(isfinite)
-# if defined(__ia64) && !defined(finite) && !defined(__GNUC__)
-# define isfinite(x) \
- ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _Isfinite(x)))
-# else
-# include <math.h>
-# define isfinite finite
-# endif
+# if !defined(isfinite)
+# if defined(__ia64) && !defined(finite) && !defined(__GNUC__)
+# define isfinite(x) ((sizeof(x) == sizeof(float) ? \
+ _Isfinitef(x) : _Isfinite(x)))
+# else
+# include <math.h>
+# define isfinite finite
# endif
+# endif
#endif
// Ancient glibc
#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
-# if !defined(isfinite)
-# define isfinite __finite
-# endif
+# if !defined(isfinite)
+# define isfinite __finite
+# endif
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
// Disable warning about strdup being deprecated.
-# pragma warning(disable : 4996)
+#pragma warning(disable : 4996)
#endif
namespace Json {
@@ -117,11 +113,10 @@ namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
#else
-typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
+typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
#endif
-static bool containsControlCharacter(const char* str)
-{
+static bool containsControlCharacter(const char* str) {
while (*str) {
if (isControlCharacter(*(str++)))
return true;
@@ -129,19 +124,17 @@ static bool containsControlCharacter(const char* str)
return false;
}
-static bool containsControlCharacter0(const char* str, unsigned len)
-{
+static bool containsControlCharacter0(const char* str, unsigned len) {
char const* end = str + len;
while (end != str) {
- if (isControlCharacter(*str) || 0 == *str)
+ if (isControlCharacter(*str) || 0==*str)
return true;
++str;
}
return false;
}
-JSONCPP_STRING valueToString(LargestInt value)
-{
+JSONCPP_STRING valueToString(LargestInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
if (value == Value::minLargestInt) {
@@ -157,8 +150,7 @@ JSONCPP_STRING valueToString(LargestInt value)
return current;
}
-JSONCPP_STRING valueToString(LargestUInt value)
-{
+JSONCPP_STRING valueToString(LargestUInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
uintToString(value, current);
@@ -168,22 +160,18 @@ JSONCPP_STRING valueToString(LargestUInt value)
#if defined(JSON_HAS_INT64)
-JSONCPP_STRING valueToString(Int value)
-{
+JSONCPP_STRING valueToString(Int value) {
return valueToString(LargestInt(value));
}
-JSONCPP_STRING valueToString(UInt value)
-{
+JSONCPP_STRING valueToString(UInt value) {
return valueToString(LargestUInt(value));
}
#endif // # if defined(JSON_HAS_INT64)
namespace {
-JSONCPP_STRING valueToString(double value, bool useSpecialFloats,
- unsigned int precision)
-{
+JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) {
// Allocate a buffer that is more than large enough to store the 16 digits of
// precision requested below.
char buffer[36];
@@ -199,8 +187,7 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats,
len = snprintf(buffer, sizeof(buffer), formatString, value);
fixNumericLocale(buffer, buffer + len);
- // try to ensure we preserve the fact that this was given to us as a double
- // on input
+ // try to ensure we preserve the fact that this was given to us as a double on input
if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
strcat(buffer, ".0");
}
@@ -208,14 +195,11 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats,
} else {
// IEEE standard states that NaN values will not compare to themselves
if (value != value) {
- len =
- snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
+ len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
} else if (value < 0) {
- len = snprintf(buffer, sizeof(buffer),
- useSpecialFloats ? "-Infinity" : "-1e+9999");
+ len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
} else {
- len = snprintf(buffer, sizeof(buffer),
- useSpecialFloats ? "Infinity" : "1e+9999");
+ len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
}
}
assert(len >= 0);
@@ -223,18 +207,11 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats,
}
}
-JSONCPP_STRING valueToString(double value)
-{
- return valueToString(value, false, 17);
-}
+JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
-JSONCPP_STRING valueToString(bool value)
-{
- return value ? "true" : "false";
-}
+JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
-JSONCPP_STRING valueToQuotedString(const char* value)
-{
+JSONCPP_STRING valueToQuotedString(const char* value) {
if (value == NULL)
return "";
// Not sure how to handle unicode...
@@ -245,50 +222,51 @@ JSONCPP_STRING valueToQuotedString(const char* value)
// Appending to JSONCPP_STRING is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
JSONCPP_STRING::size_type maxsize =
- strlen(value) * 2 + 3; // allescaped+quotes+NULL
+ strlen(value) * 2 + 3; // allescaped+quotes+NULL
JSONCPP_STRING result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
for (const char* c = value; *c != 0; ++c) {
switch (*c) {
- case '\"':
- result += "\\\"";
- break;
- case '\\':
- result += "\\\\";
- break;
- case '\b':
- result += "\\b";
- break;
- case '\f':
- result += "\\f";
- break;
- case '\n':
- result += "\\n";
- break;
- case '\r':
- result += "\\r";
- break;
- case '\t':
- result += "\\t";
- break;
- // case '/':
- // Even though \/ is considered a legal escape in JSON, a bare
- // slash is also legal, so I see no reason to escape it.
- // (I hope I am not misunderstanding something.
- // blep notes: actually escaping \/ may be useful in javascript to avoid
- // </ sequence. Should add a flag to allow this compatibility mode and
- // prevent this sequence from occurring.
- default:
- if (isControlCharacter(*c)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
- } else {
- result += *c;
- }
- break;
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ // case '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.
+ // blep notes: actually escaping \/ may be useful in javascript to avoid </
+ // sequence.
+ // Should add a flag to allow this compatibility mode and prevent this
+ // sequence from occurring.
+ default:
+ if (isControlCharacter(*c)) {
+ JSONCPP_OSTRINGSTREAM oss;
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+ << std::setw(4) << static_cast<int>(*c);
+ result += oss.str();
+ } else {
+ result += *c;
+ }
+ break;
}
}
result += "\"";
@@ -296,8 +274,7 @@ JSONCPP_STRING valueToQuotedString(const char* value)
}
// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
-static char const* strnpbrk(char const* s, char const* accept, size_t n)
-{
+static char const* strnpbrk(char const* s, char const* accept, size_t n) {
assert((s || !n) && accept);
char const* const end = s + n;
@@ -311,8 +288,7 @@ static char const* strnpbrk(char const* s, char const* accept, size_t n)
}
return NULL;
}
-static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length)
-{
+static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
if (value == NULL)
return "";
// Not sure how to handle unicode...
@@ -322,51 +298,53 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length)
// We have to walk value and escape any special characters.
// Appending to JSONCPP_STRING is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
- JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
+ JSONCPP_STRING::size_type maxsize =
+ length * 2 + 3; // allescaped+quotes+NULL
JSONCPP_STRING result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
char const* end = value + length;
for (const char* c = value; c != end; ++c) {
switch (*c) {
- case '\"':
- result += "\\\"";
- break;
- case '\\':
- result += "\\\\";
- break;
- case '\b':
- result += "\\b";
- break;
- case '\f':
- result += "\\f";
- break;
- case '\n':
- result += "\\n";
- break;
- case '\r':
- result += "\\r";
- break;
- case '\t':
- result += "\\t";
- break;
- // case '/':
- // Even though \/ is considered a legal escape in JSON, a bare
- // slash is also legal, so I see no reason to escape it.
- // (I hope I am not misunderstanding something.)
- // blep notes: actually escaping \/ may be useful in javascript to avoid
- // </ sequence. Should add a flag to allow this compatibility mode and
- // prevent this sequence from occurring.
- default:
- if ((isControlCharacter(*c)) || (*c == 0)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
- } else {
- result += *c;
- }
- break;
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ // case '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.)
+ // blep notes: actually escaping \/ may be useful in javascript to avoid </
+ // sequence.
+ // Should add a flag to allow this compatibility mode and prevent this
+ // sequence from occurring.
+ default:
+ if ((isControlCharacter(*c)) || (*c == 0)) {
+ JSONCPP_OSTRINGSTREAM oss;
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+ << std::setw(4) << static_cast<int>(*c);
+ result += oss.str();
+ } else {
+ result += *c;
+ }
+ break;
}
}
result += "\"";
@@ -375,98 +353,80 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length)
// Class Writer
// //////////////////////////////////////////////////////////////////
-Writer::~Writer()
-{
-}
+Writer::~Writer() {}
// Class FastWriter
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
- : yamlCompatiblityEnabled_(false)
- , dropNullPlaceholders_(false)
- , omitEndingLineFeed_(false)
-{
-}
+ : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
+ omitEndingLineFeed_(false) {}
-void FastWriter::enableYAMLCompatibility()
-{
- this->yamlCompatiblityEnabled_ = true;
-}
+void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
-void FastWriter::dropNullPlaceholders()
-{
- this->dropNullPlaceholders_ = true;
-}
+void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
-void FastWriter::omitEndingLineFeed()
-{
- this->omitEndingLineFeed_ = true;
-}
+void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
-JSONCPP_STRING FastWriter::write(const Value& root)
-{
- this->document_.clear();
- this->writeValue(root);
- if (!this->omitEndingLineFeed_)
- this->document_ += "\n";
- return this->document_;
+JSONCPP_STRING FastWriter::write(const Value& root) {
+ document_.clear();
+ writeValue(root);
+ if (!omitEndingLineFeed_)
+ document_ += "\n";
+ return document_;
}
-void FastWriter::writeValue(const Value& value)
-{
+void FastWriter::writeValue(const Value& value) {
switch (value.type()) {
- case nullValue:
- if (!this->dropNullPlaceholders_)
- this->document_ += "null";
- break;
- case intValue:
- this->document_ += valueToString(value.asLargestInt());
- break;
- case uintValue:
- this->document_ += valueToString(value.asLargestUInt());
- break;
- case realValue:
- this->document_ += valueToString(value.asDouble());
- break;
- case stringValue: {
- // Is NULL possible for value.string_? No.
- char const* str;
- char const* end;
- bool ok = value.getString(&str, &end);
- if (ok)
- this->document_ +=
- valueToQuotedStringN(str, static_cast<unsigned>(end - str));
- break;
+ case nullValue:
+ if (!dropNullPlaceholders_)
+ document_ += "null";
+ break;
+ case intValue:
+ document_ += valueToString(value.asLargestInt());
+ break;
+ case uintValue:
+ document_ += valueToString(value.asLargestUInt());
+ break;
+ case realValue:
+ document_ += valueToString(value.asDouble());
+ break;
+ case stringValue:
+ {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
+ break;
+ }
+ case booleanValue:
+ document_ += valueToString(value.asBool());
+ break;
+ case arrayValue: {
+ document_ += '[';
+ ArrayIndex size = value.size();
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (index > 0)
+ document_ += ',';
+ writeValue(value[index]);
}
- case booleanValue:
- this->document_ += valueToString(value.asBool());
- break;
- case arrayValue: {
- this->document_ += '[';
- ArrayIndex size = value.size();
- for (ArrayIndex index = 0; index < size; ++index) {
- if (index > 0)
- this->document_ += ',';
- this->writeValue(value[index]);
- }
- this->document_ += ']';
- } break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- this->document_ += '{';
- for (Value::Members::iterator it = members.begin(); it != members.end();
- ++it) {
- const JSONCPP_STRING& name = *it;
- if (it != members.begin())
- this->document_ += ',';
- this->document_ += valueToQuotedStringN(
- name.data(), static_cast<unsigned>(name.length()));
- this->document_ += this->yamlCompatiblityEnabled_ ? ": " : ":";
- this->writeValue(value[name]);
- }
- this->document_ += '}';
- } break;
+ document_ += ']';
+ } break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ document_ += '{';
+ for (Value::Members::iterator it = members.begin(); it != members.end();
+ ++it) {
+ const JSONCPP_STRING& name = *it;
+ if (it != members.begin())
+ document_ += ',';
+ document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
+ document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+ writeValue(value[name]);
+ }
+ document_ += '}';
+ } break;
}
}
@@ -474,498 +434,454 @@ void FastWriter::writeValue(const Value& value)
// //////////////////////////////////////////////////////////////////
StyledWriter::StyledWriter()
- : rightMargin_(74)
- , indentSize_(3)
- , addChildValues_()
-{
-}
+ : rightMargin_(74), indentSize_(3), addChildValues_() {}
-JSONCPP_STRING StyledWriter::write(const Value& root)
-{
- this->document_.clear();
- this->addChildValues_ = false;
- this->indentString_.clear();
- this->writeCommentBeforeValue(root);
- this->writeValue(root);
- this->writeCommentAfterValueOnSameLine(root);
- this->document_ += "\n";
- return this->document_;
+JSONCPP_STRING StyledWriter::write(const Value& root) {
+ document_.clear();
+ addChildValues_ = false;
+ indentString_.clear();
+ writeCommentBeforeValue(root);
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ document_ += "\n";
+ return document_;
}
-void StyledWriter::writeValue(const Value& value)
-{
+void StyledWriter::writeValue(const Value& value) {
switch (value.type()) {
- case nullValue:
- this->pushValue("null");
- break;
- case intValue:
- this->pushValue(valueToString(value.asLargestInt()));
- break;
- case uintValue:
- this->pushValue(valueToString(value.asLargestUInt()));
- break;
- case realValue:
- this->pushValue(valueToString(value.asDouble()));
- break;
- case stringValue: {
- // Is NULL possible for value.string_? No.
- char const* str;
- char const* end;
- bool ok = value.getString(&str, &end);
- if (ok)
- this->pushValue(
- valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
- else
- this->pushValue("");
- break;
- }
- case booleanValue:
- this->pushValue(valueToString(value.asBool()));
- break;
- case arrayValue:
- this->writeArrayValue(value);
- break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- if (members.empty())
- this->pushValue("{}");
- else {
- this->writeWithIndent("{");
- this->indent();
- Value::Members::iterator it = members.begin();
- for (;;) {
- const JSONCPP_STRING& name = *it;
- const Value& childValue = value[name];
- this->writeCommentBeforeValue(childValue);
- this->writeWithIndent(valueToQuotedString(name.c_str()));
- this->document_ += " : ";
- this->writeValue(childValue);
- if (++it == members.end()) {
- this->writeCommentAfterValueOnSameLine(childValue);
- break;
- }
- this->document_ += ',';
- this->writeCommentAfterValueOnSameLine(childValue);
+ case nullValue:
+ pushValue("null");
+ break;
+ case intValue:
+ pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue:
+ {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+ else pushValue("");
+ break;
+ }
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ Value::Members::iterator it = members.begin();
+ for (;;) {
+ const JSONCPP_STRING& name = *it;
+ const Value& childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedString(name.c_str()));
+ document_ += " : ";
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
}
- this->unindent();
- this->writeWithIndent("}");
+ document_ += ',';
+ writeCommentAfterValueOnSameLine(childValue);
}
- } break;
+ unindent();
+ writeWithIndent("}");
+ }
+ } break;
}
}
-void StyledWriter::writeArrayValue(const Value& value)
-{
+void StyledWriter::writeArrayValue(const Value& value) {
unsigned size = value.size();
if (size == 0)
- this->pushValue("[]");
+ pushValue("[]");
else {
- bool isArrayMultiLine = this->isMultineArray(value);
+ bool isArrayMultiLine = isMultineArray(value);
if (isArrayMultiLine) {
- this->writeWithIndent("[");
- this->indent();
- bool hasChildValue = !this->childValues_.empty();
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
unsigned index = 0;
for (;;) {
const Value& childValue = value[index];
- this->writeCommentBeforeValue(childValue);
+ writeCommentBeforeValue(childValue);
if (hasChildValue)
- this->writeWithIndent(this->childValues_[index]);
+ writeWithIndent(childValues_[index]);
else {
- this->writeIndent();
- this->writeValue(childValue);
+ writeIndent();
+ writeValue(childValue);
}
if (++index == size) {
- this->writeCommentAfterValueOnSameLine(childValue);
+ writeCommentAfterValueOnSameLine(childValue);
break;
}
- this->document_ += ',';
- this->writeCommentAfterValueOnSameLine(childValue);
+ document_ += ',';
+ writeCommentAfterValueOnSameLine(childValue);
}
- this->unindent();
- this->writeWithIndent("]");
+ unindent();
+ writeWithIndent("]");
} else // output on a single line
{
- assert(this->childValues_.size() == size);
- this->document_ += "[ ";
+ assert(childValues_.size() == size);
+ document_ += "[ ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- this->document_ += ", ";
- this->document_ += this->childValues_[index];
+ document_ += ", ";
+ document_ += childValues_[index];
}
- this->document_ += " ]";
+ document_ += " ]";
}
}
}
-bool StyledWriter::isMultineArray(const Value& value)
-{
+bool StyledWriter::isMultineArray(const Value& value) {
ArrayIndex const size = value.size();
- bool isMultiLine = size * 3 >= this->rightMargin_;
- this->childValues_.clear();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
- this->childValues_.reserve(size);
- this->addChildValues_ = true;
+ childValues_.reserve(size);
+ addChildValues_ = true;
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
- if (this->hasCommentForValue(value[index])) {
+ if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
- this->writeValue(value[index]);
- lineLength +=
- static_cast<ArrayIndex>(this->childValues_[index].length());
+ writeValue(value[index]);
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
}
- this->addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= this->rightMargin_;
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
}
return isMultiLine;
}
-void StyledWriter::pushValue(const JSONCPP_STRING& value)
-{
- if (this->addChildValues_)
- this->childValues_.push_back(value);
+void StyledWriter::pushValue(const JSONCPP_STRING& value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
else
- this->document_ += value;
+ document_ += value;
}
-void StyledWriter::writeIndent()
-{
- if (!this->document_.empty()) {
- char last = this->document_[this->document_.length() - 1];
+void StyledWriter::writeIndent() {
+ if (!document_.empty()) {
+ char last = document_[document_.length() - 1];
if (last == ' ') // already indented
return;
if (last != '\n') // Comments may add new-line
- this->document_ += '\n';
+ document_ += '\n';
}
- this->document_ += this->indentString_;
+ document_ += indentString_;
}
-void StyledWriter::writeWithIndent(const JSONCPP_STRING& value)
-{
- this->writeIndent();
- this->document_ += value;
+void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
+ writeIndent();
+ document_ += value;
}
-void StyledWriter::indent()
-{
- this->indentString_ += JSONCPP_STRING(this->indentSize_, ' ');
-}
+void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
-void StyledWriter::unindent()
-{
- assert(this->indentString_.size() >= this->indentSize_);
- this->indentString_.resize(this->indentString_.size() - this->indentSize_);
+void StyledWriter::unindent() {
+ assert(indentString_.size() >= indentSize_);
+ indentString_.resize(indentString_.size() - indentSize_);
}
-void StyledWriter::writeCommentBeforeValue(const Value& root)
-{
+void StyledWriter::writeCommentBeforeValue(const Value& root) {
if (!root.hasComment(commentBefore))
return;
- this->document_ += "\n";
- this->writeIndent();
+ document_ += "\n";
+ writeIndent();
const JSONCPP_STRING& comment = root.getComment(commentBefore);
JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
- this->document_ += *iter;
- if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
- this->writeIndent();
+ document_ += *iter;
+ if (*iter == '\n' &&
+ (iter != comment.end() && *(iter + 1) == '/'))
+ writeIndent();
++iter;
}
// Comments are stripped of trailing newlines, so add one here
- this->document_ += "\n";
+ document_ += "\n";
}
-void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root)
-{
+void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
if (root.hasComment(commentAfterOnSameLine))
- this->document_ += " " + root.getComment(commentAfterOnSameLine);
+ document_ += " " + root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- this->document_ += "\n";
- this->document_ += root.getComment(commentAfter);
- this->document_ += "\n";
+ document_ += "\n";
+ document_ += root.getComment(commentAfter);
+ document_ += "\n";
}
}
-bool StyledWriter::hasCommentForValue(const Value& value)
-{
+bool StyledWriter::hasCommentForValue(const Value& value) {
return value.hasComment(commentBefore) ||
- value.hasComment(commentAfterOnSameLine) || value.hasComment(commentAfter);
+ value.hasComment(commentAfterOnSameLine) ||
+ value.hasComment(commentAfter);
}
// Class StyledStreamWriter
// //////////////////////////////////////////////////////////////////
StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
- : document_(NULL)
- , rightMargin_(74)
- , indentation_(indentation)
- , addChildValues_()
-{
-}
-
-void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root)
-{
- this->document_ = &out;
- this->addChildValues_ = false;
- this->indentString_.clear();
- this->indented_ = true;
- this->writeCommentBeforeValue(root);
- if (!this->indented_)
- this->writeIndent();
- this->indented_ = true;
- this->writeValue(root);
- this->writeCommentAfterValueOnSameLine(root);
- *this->document_ << "\n";
- this->document_ = NULL; // Forget the stream, for safety.
-}
-
-void StyledStreamWriter::writeValue(const Value& value)
-{
+ : document_(NULL), rightMargin_(74), indentation_(indentation),
+ addChildValues_() {}
+
+void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
+ document_ = &out;
+ addChildValues_ = false;
+ indentString_.clear();
+ indented_ = true;
+ writeCommentBeforeValue(root);
+ if (!indented_) writeIndent();
+ indented_ = true;
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ *document_ << "\n";
+ document_ = NULL; // Forget the stream, for safety.
+}
+
+void StyledStreamWriter::writeValue(const Value& value) {
switch (value.type()) {
- case nullValue:
- this->pushValue("null");
- break;
- case intValue:
- this->pushValue(valueToString(value.asLargestInt()));
- break;
- case uintValue:
- this->pushValue(valueToString(value.asLargestUInt()));
- break;
- case realValue:
- this->pushValue(valueToString(value.asDouble()));
- break;
- case stringValue: {
- // Is NULL possible for value.string_? No.
- char const* str;
- char const* end;
- bool ok = value.getString(&str, &end);
- if (ok)
- this->pushValue(
- valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
- else
- this->pushValue("");
- break;
- }
- case booleanValue:
- this->pushValue(valueToString(value.asBool()));
- break;
- case arrayValue:
- this->writeArrayValue(value);
- break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- if (members.empty())
- this->pushValue("{}");
- else {
- this->writeWithIndent("{");
- this->indent();
- Value::Members::iterator it = members.begin();
- for (;;) {
- const JSONCPP_STRING& name = *it;
- const Value& childValue = value[name];
- this->writeCommentBeforeValue(childValue);
- this->writeWithIndent(valueToQuotedString(name.c_str()));
- *this->document_ << " : ";
- this->writeValue(childValue);
- if (++it == members.end()) {
- this->writeCommentAfterValueOnSameLine(childValue);
- break;
- }
- *this->document_ << ",";
- this->writeCommentAfterValueOnSameLine(childValue);
+ case nullValue:
+ pushValue("null");
+ break;
+ case intValue:
+ pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue:
+ {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+ else pushValue("");
+ break;
+ }
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ Value::Members::iterator it = members.begin();
+ for (;;) {
+ const JSONCPP_STRING& name = *it;
+ const Value& childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedString(name.c_str()));
+ *document_ << " : ";
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
}
- this->unindent();
- this->writeWithIndent("}");
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
}
- } break;
+ unindent();
+ writeWithIndent("}");
+ }
+ } break;
}
}
-void StyledStreamWriter::writeArrayValue(const Value& value)
-{
+void StyledStreamWriter::writeArrayValue(const Value& value) {
unsigned size = value.size();
if (size == 0)
- this->pushValue("[]");
+ pushValue("[]");
else {
- bool isArrayMultiLine = this->isMultineArray(value);
+ bool isArrayMultiLine = isMultineArray(value);
if (isArrayMultiLine) {
- this->writeWithIndent("[");
- this->indent();
- bool hasChildValue = !this->childValues_.empty();
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
unsigned index = 0;
for (;;) {
const Value& childValue = value[index];
- this->writeCommentBeforeValue(childValue);
+ writeCommentBeforeValue(childValue);
if (hasChildValue)
- this->writeWithIndent(this->childValues_[index]);
+ writeWithIndent(childValues_[index]);
else {
- if (!this->indented_)
- this->writeIndent();
- this->indented_ = true;
- this->writeValue(childValue);
- this->indented_ = false;
+ if (!indented_) writeIndent();
+ indented_ = true;
+ writeValue(childValue);
+ indented_ = false;
}
if (++index == size) {
- this->writeCommentAfterValueOnSameLine(childValue);
+ writeCommentAfterValueOnSameLine(childValue);
break;
}
- *this->document_ << ",";
- this->writeCommentAfterValueOnSameLine(childValue);
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
}
- this->unindent();
- this->writeWithIndent("]");
+ unindent();
+ writeWithIndent("]");
} else // output on a single line
{
- assert(this->childValues_.size() == size);
- *this->document_ << "[ ";
+ assert(childValues_.size() == size);
+ *document_ << "[ ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- *this->document_ << ", ";
- *this->document_ << this->childValues_[index];
+ *document_ << ", ";
+ *document_ << childValues_[index];
}
- *this->document_ << " ]";
+ *document_ << " ]";
}
}
}
-bool StyledStreamWriter::isMultineArray(const Value& value)
-{
+bool StyledStreamWriter::isMultineArray(const Value& value) {
ArrayIndex const size = value.size();
- bool isMultiLine = size * 3 >= this->rightMargin_;
- this->childValues_.clear();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
- this->childValues_.reserve(size);
- this->addChildValues_ = true;
+ childValues_.reserve(size);
+ addChildValues_ = true;
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
- if (this->hasCommentForValue(value[index])) {
+ if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
- this->writeValue(value[index]);
- lineLength +=
- static_cast<ArrayIndex>(this->childValues_[index].length());
+ writeValue(value[index]);
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
}
- this->addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= this->rightMargin_;
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
}
return isMultiLine;
}
-void StyledStreamWriter::pushValue(const JSONCPP_STRING& value)
-{
- if (this->addChildValues_)
- this->childValues_.push_back(value);
+void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
else
- *this->document_ << value;
+ *document_ << value;
}
-void StyledStreamWriter::writeIndent()
-{
+void StyledStreamWriter::writeIndent() {
// blep intended this to look at the so-far-written string
// to determine whether we are already indented, but
// with a stream we cannot do that. So we rely on some saved state.
// The caller checks indented_.
- *this->document_ << '\n' << this->indentString_;
+ *document_ << '\n' << indentString_;
}
-void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value)
-{
- if (!this->indented_)
- this->writeIndent();
- *this->document_ << value;
- this->indented_ = false;
+void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
+ if (!indented_) writeIndent();
+ *document_ << value;
+ indented_ = false;
}
-void StyledStreamWriter::indent()
-{
- this->indentString_ += this->indentation_;
-}
+void StyledStreamWriter::indent() { indentString_ += indentation_; }
-void StyledStreamWriter::unindent()
-{
- assert(this->indentString_.size() >= this->indentation_.size());
- this->indentString_.resize(this->indentString_.size() -
- this->indentation_.size());
+void StyledStreamWriter::unindent() {
+ assert(indentString_.size() >= indentation_.size());
+ indentString_.resize(indentString_.size() - indentation_.size());
}
-void StyledStreamWriter::writeCommentBeforeValue(const Value& root)
-{
+void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
if (!root.hasComment(commentBefore))
return;
- if (!this->indented_)
- this->writeIndent();
+ if (!indented_) writeIndent();
const JSONCPP_STRING& comment = root.getComment(commentBefore);
JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
- *this->document_ << *iter;
- if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
+ *document_ << *iter;
+ if (*iter == '\n' &&
+ (iter != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would include newline
- *this->document_ << this->indentString_;
+ *document_ << indentString_;
++iter;
}
- this->indented_ = false;
+ indented_ = false;
}
-void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root)
-{
+void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
if (root.hasComment(commentAfterOnSameLine))
- *this->document_ << ' ' << root.getComment(commentAfterOnSameLine);
+ *document_ << ' ' << root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- this->writeIndent();
- *this->document_ << root.getComment(commentAfter);
+ writeIndent();
+ *document_ << root.getComment(commentAfter);
}
- this->indented_ = false;
+ indented_ = false;
}
-bool StyledStreamWriter::hasCommentForValue(const Value& value)
-{
+bool StyledStreamWriter::hasCommentForValue(const Value& value) {
return value.hasComment(commentBefore) ||
- value.hasComment(commentAfterOnSameLine) || value.hasComment(commentAfter);
+ value.hasComment(commentAfterOnSameLine) ||
+ value.hasComment(commentAfter);
}
//////////////////////////
// BuiltStyledStreamWriter
/// Scoped enums are not available until C++11.
-struct CommentStyle
-{
+struct CommentStyle {
/// Decide whether to write comments.
- enum Enum
- {
- None, ///< Drop all comments.
- Most, ///< Recover odd behavior of previous versions (not implemented yet).
- All ///< Keep all comments.
+ enum Enum {
+ None, ///< Drop all comments.
+ Most, ///< Recover odd behavior of previous versions (not implemented yet).
+ All ///< Keep all comments.
};
};
struct BuiltStyledStreamWriter : public StreamWriter
{
- BuiltStyledStreamWriter(JSONCPP_STRING const& indentation,
- CommentStyle::Enum cs,
- JSONCPP_STRING const& colonSymbol,
- JSONCPP_STRING const& nullSymbol,
- JSONCPP_STRING const& endingLineFeedSymbol,
- bool useSpecialFloats, unsigned int precision);
+ BuiltStyledStreamWriter(
+ JSONCPP_STRING const& indentation,
+ CommentStyle::Enum cs,
+ JSONCPP_STRING const& colonSymbol,
+ JSONCPP_STRING const& nullSymbol,
+ JSONCPP_STRING const& endingLineFeedSymbol,
+ bool useSpecialFloats,
+ unsigned int precision);
int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
-
private:
void writeValue(Value const& value);
void writeArrayValue(Value const& value);
@@ -995,10 +911,13 @@ private:
unsigned int precision_;
};
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
- JSONCPP_STRING const& indentation, CommentStyle::Enum cs,
- JSONCPP_STRING const& colonSymbol, JSONCPP_STRING const& nullSymbol,
- JSONCPP_STRING const& endingLineFeedSymbol, bool useSpecialFloats,
- unsigned int precision)
+ JSONCPP_STRING const& indentation,
+ CommentStyle::Enum cs,
+ JSONCPP_STRING const& colonSymbol,
+ JSONCPP_STRING const& nullSymbol,
+ JSONCPP_STRING const& endingLineFeedSymbol,
+ bool useSpecialFloats,
+ unsigned int precision)
: rightMargin_(74)
, indentation_(indentation)
, cs_(cs)
@@ -1013,276 +932,247 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
}
int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
{
- this->sout_ = sout;
- this->addChildValues_ = false;
- this->indented_ = true;
- this->indentString_.clear();
- this->writeCommentBeforeValue(root);
- if (!this->indented_)
- this->writeIndent();
- this->indented_ = true;
- this->writeValue(root);
- this->writeCommentAfterValueOnSameLine(root);
- *this->sout_ << this->endingLineFeedSymbol_;
- this->sout_ = NULL;
+ sout_ = sout;
+ addChildValues_ = false;
+ indented_ = true;
+ indentString_.clear();
+ writeCommentBeforeValue(root);
+ if (!indented_) writeIndent();
+ indented_ = true;
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ *sout_ << endingLineFeedSymbol_;
+ sout_ = NULL;
return 0;
}
-void BuiltStyledStreamWriter::writeValue(Value const& value)
-{
+void BuiltStyledStreamWriter::writeValue(Value const& value) {
switch (value.type()) {
- case nullValue:
- this->pushValue(this->nullSymbol_);
- break;
- case intValue:
- this->pushValue(valueToString(value.asLargestInt()));
- break;
- case uintValue:
- this->pushValue(valueToString(value.asLargestUInt()));
- break;
- case realValue:
- this->pushValue(valueToString(value.asDouble(), this->useSpecialFloats_,
- this->precision_));
- break;
- case stringValue: {
- // Is NULL is possible for value.string_? No.
- char const* str;
- char const* end;
- bool ok = value.getString(&str, &end);
- if (ok)
- this->pushValue(
- valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
- else
- this->pushValue("");
- break;
- }
- case booleanValue:
- this->pushValue(valueToString(value.asBool()));
- break;
- case arrayValue:
- this->writeArrayValue(value);
- break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- if (members.empty())
- this->pushValue("{}");
- else {
- this->writeWithIndent("{");
- this->indent();
- Value::Members::iterator it = members.begin();
- for (;;) {
- JSONCPP_STRING const& name = *it;
- Value const& childValue = value[name];
- this->writeCommentBeforeValue(childValue);
- this->writeWithIndent(valueToQuotedStringN(
- name.data(), static_cast<unsigned>(name.length())));
- *this->sout_ << this->colonSymbol_;
- this->writeValue(childValue);
- if (++it == members.end()) {
- this->writeCommentAfterValueOnSameLine(childValue);
- break;
- }
- *this->sout_ << ",";
- this->writeCommentAfterValueOnSameLine(childValue);
+ case nullValue:
+ pushValue(nullSymbol_);
+ break;
+ case intValue:
+ pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
+ break;
+ case stringValue:
+ {
+ // Is NULL is possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+ else pushValue("");
+ break;
+ }
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ Value::Members::iterator it = members.begin();
+ for (;;) {
+ JSONCPP_STRING const& name = *it;
+ Value const& childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
+ *sout_ << colonSymbol_;
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
}
- this->unindent();
- this->writeWithIndent("}");
+ *sout_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
}
- } break;
+ unindent();
+ writeWithIndent("}");
+ }
+ } break;
}
}
-void BuiltStyledStreamWriter::writeArrayValue(Value const& value)
-{
+void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
unsigned size = value.size();
if (size == 0)
- this->pushValue("[]");
+ pushValue("[]");
else {
- bool isMultiLine =
- (this->cs_ == CommentStyle::All) || this->isMultineArray(value);
+ bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
if (isMultiLine) {
- this->writeWithIndent("[");
- this->indent();
- bool hasChildValue = !this->childValues_.empty();
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
unsigned index = 0;
for (;;) {
Value const& childValue = value[index];
- this->writeCommentBeforeValue(childValue);
+ writeCommentBeforeValue(childValue);
if (hasChildValue)
- this->writeWithIndent(this->childValues_[index]);
+ writeWithIndent(childValues_[index]);
else {
- if (!this->indented_)
- this->writeIndent();
- this->indented_ = true;
- this->writeValue(childValue);
- this->indented_ = false;
+ if (!indented_) writeIndent();
+ indented_ = true;
+ writeValue(childValue);
+ indented_ = false;
}
if (++index == size) {
- this->writeCommentAfterValueOnSameLine(childValue);
+ writeCommentAfterValueOnSameLine(childValue);
break;
}
- *this->sout_ << ",";
- this->writeCommentAfterValueOnSameLine(childValue);
+ *sout_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
}
- this->unindent();
- this->writeWithIndent("]");
+ unindent();
+ writeWithIndent("]");
} else // output on a single line
{
- assert(this->childValues_.size() == size);
- *this->sout_ << "[";
- if (!this->indentation_.empty())
- *this->sout_ << " ";
+ assert(childValues_.size() == size);
+ *sout_ << "[";
+ if (!indentation_.empty()) *sout_ << " ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- *this->sout_ << ((!this->indentation_.empty()) ? ", " : ",");
- *this->sout_ << this->childValues_[index];
+ *sout_ << ((!indentation_.empty()) ? ", " : ",");
+ *sout_ << childValues_[index];
}
- if (!this->indentation_.empty())
- *this->sout_ << " ";
- *this->sout_ << "]";
+ if (!indentation_.empty()) *sout_ << " ";
+ *sout_ << "]";
}
}
}
-bool BuiltStyledStreamWriter::isMultineArray(Value const& value)
-{
+bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
ArrayIndex const size = value.size();
- bool isMultiLine = size * 3 >= this->rightMargin_;
- this->childValues_.clear();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
Value const& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
- this->childValues_.reserve(size);
- this->addChildValues_ = true;
+ childValues_.reserve(size);
+ addChildValues_ = true;
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
- this->writeValue(value[index]);
- lineLength +=
- static_cast<ArrayIndex>(this->childValues_[index].length());
+ writeValue(value[index]);
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
}
- this->addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= this->rightMargin_;
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
}
return isMultiLine;
}
-void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value)
-{
- if (this->addChildValues_)
- this->childValues_.push_back(value);
+void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
else
- *this->sout_ << value;
+ *sout_ << value;
}
-void BuiltStyledStreamWriter::writeIndent()
-{
+void BuiltStyledStreamWriter::writeIndent() {
// blep intended this to look at the so-far-written string
// to determine whether we are already indented, but
// with a stream we cannot do that. So we rely on some saved state.
// The caller checks indented_.
- if (!this->indentation_.empty()) {
+ if (!indentation_.empty()) {
// In this case, drop newlines too.
- *this->sout_ << '\n' << this->indentString_;
+ *sout_ << '\n' << indentString_;
}
}
-void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value)
-{
- if (!this->indented_)
- this->writeIndent();
- *this->sout_ << value;
- this->indented_ = false;
+void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
+ if (!indented_) writeIndent();
+ *sout_ << value;
+ indented_ = false;
}
-void BuiltStyledStreamWriter::indent()
-{
- this->indentString_ += this->indentation_;
-}
+void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
-void BuiltStyledStreamWriter::unindent()
-{
- assert(this->indentString_.size() >= this->indentation_.size());
- this->indentString_.resize(this->indentString_.size() -
- this->indentation_.size());
+void BuiltStyledStreamWriter::unindent() {
+ assert(indentString_.size() >= indentation_.size());
+ indentString_.resize(indentString_.size() - indentation_.size());
}
-void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root)
-{
- if (this->cs_ == CommentStyle::None)
- return;
+void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
+ if (cs_ == CommentStyle::None) return;
if (!root.hasComment(commentBefore))
return;
- if (!this->indented_)
- this->writeIndent();
+ if (!indented_) writeIndent();
const JSONCPP_STRING& comment = root.getComment(commentBefore);
JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
- *this->sout_ << *iter;
- if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
+ *sout_ << *iter;
+ if (*iter == '\n' &&
+ (iter != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would write extra newline
- *this->sout_ << this->indentString_;
+ *sout_ << indentString_;
++iter;
}
- this->indented_ = false;
+ indented_ = false;
}
-void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
- Value const& root)
-{
- if (this->cs_ == CommentStyle::None)
- return;
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
+ if (cs_ == CommentStyle::None) return;
if (root.hasComment(commentAfterOnSameLine))
- *this->sout_ << " " + root.getComment(commentAfterOnSameLine);
+ *sout_ << " " + root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- this->writeIndent();
- *this->sout_ << root.getComment(commentAfter);
+ writeIndent();
+ *sout_ << root.getComment(commentAfter);
}
}
// static
-bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value)
-{
+bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
return value.hasComment(commentBefore) ||
- value.hasComment(commentAfterOnSameLine) || value.hasComment(commentAfter);
+ value.hasComment(commentAfterOnSameLine) ||
+ value.hasComment(commentAfter);
}
///////////////
// StreamWriter
StreamWriter::StreamWriter()
- : sout_(NULL)
+ : sout_(NULL)
{
}
StreamWriter::~StreamWriter()
{
}
StreamWriter::Factory::~Factory()
-{
-}
+{}
StreamWriterBuilder::StreamWriterBuilder()
{
- setDefaults(&this->settings_);
+ setDefaults(&settings_);
}
StreamWriterBuilder::~StreamWriterBuilder()
-{
-}
+{}
StreamWriter* StreamWriterBuilder::newStreamWriter() const
{
- JSONCPP_STRING indentation = this->settings_["indentation"].asString();
- JSONCPP_STRING cs_str = this->settings_["commentStyle"].asString();
- bool eyc = this->settings_["enableYAMLCompatibility"].asBool();
- bool dnp = this->settings_["dropNullPlaceholders"].asBool();
- bool usf = this->settings_["useSpecialFloats"].asBool();
- unsigned int pre = this->settings_["precision"].asUInt();
+ JSONCPP_STRING indentation = settings_["indentation"].asString();
+ JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
+ bool eyc = settings_["enableYAMLCompatibility"].asBool();
+ bool dnp = settings_["dropNullPlaceholders"].asBool();
+ bool usf = settings_["useSpecialFloats"].asBool();
+ unsigned int pre = settings_["precision"].asUInt();
CommentStyle::Enum cs = CommentStyle::All;
if (cs_str == "All") {
cs = CommentStyle::All;
@@ -1301,11 +1191,11 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const
if (dnp) {
nullSymbol.clear();
}
- if (pre > 17)
- pre = 17;
+ if (pre > 17) pre = 17;
JSONCPP_STRING endingLineFeedSymbol;
- return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
- endingLineFeedSymbol, usf, pre);
+ return new BuiltStyledStreamWriter(
+ indentation, cs,
+ colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
}
static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
{
@@ -1320,24 +1210,23 @@ static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
bool StreamWriterBuilder::validate(Json::Value* invalid) const
{
Json::Value my_invalid;
- if (!invalid)
- invalid = &my_invalid; // so we do not need to test for NULL
+ if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
Json::Value& inv = *invalid;
std::set<JSONCPP_STRING> valid_keys;
getValidWriterKeys(&valid_keys);
- Value::Members keys = this->settings_.getMemberNames();
+ Value::Members keys = settings_.getMemberNames();
size_t n = keys.size();
for (size_t i = 0; i < n; ++i) {
JSONCPP_STRING const& key = keys[i];
if (valid_keys.find(key) == valid_keys.end()) {
- inv[key] = this->settings_[key];
+ inv[key] = settings_[key];
}
}
return 0u == inv.size();
}
Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
{
- return this->settings_[key];
+ return settings_[key];
}
// static
void StreamWriterBuilder::setDefaults(Json::Value* settings)
@@ -1352,17 +1241,14 @@ void StreamWriterBuilder::setDefaults(Json::Value* settings)
//! [StreamWriterBuilderDefaults]
}
-JSONCPP_STRING writeString(StreamWriter::Factory const& builder,
- Value const& root)
-{
+JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
JSONCPP_OSTRINGSTREAM sout;
StreamWriterPtr const writer(builder.newStreamWriter());
writer->write(root, &sout);
return sout.str();
}
-JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root)
-{
+JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
StreamWriterBuilder builder;
StreamWriterPtr const writer(builder.newStreamWriter());
writer->write(root, &sout);
diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt
index 689d98afb..79452ffff 100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@ -94,7 +94,7 @@ SET(CMAKE_REQUIRED_FLAGS)
# Disable warnings to avoid changing 3rd party code.
IF(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmliblzma/CMakeLists.txt b/Utilities/cmliblzma/CMakeLists.txt
index 32a14dc23..4820a8fd0 100644
--- a/Utilities/cmliblzma/CMakeLists.txt
+++ b/Utilities/cmliblzma/CMakeLists.txt
@@ -6,6 +6,12 @@ include(CheckSymbolExists)
include(CheckTypeSize)
include(TestBigEndian)
+if(WIN32)
+ add_definitions(-DMYTHREAD_VISTA)
+else()
+ add_definitions(-DMYTHREAD_POSIX)
+endif()
+
CHECK_INCLUDE_FILE(byteswap.h HAVE_BYTESWAP_H)
CHECK_INCLUDE_FILE(limits.h HAVE_LIMITS_H)
CHECK_INCLUDE_FILE(memory.h HAVE_MEMORY_H)
@@ -60,7 +66,10 @@ set(HAVE_MF_HC3 1)
set(HAVE_MF_HC4 1)
SET(LZMA_SRCS
+ common/mythread.h
common/sysdefs.h
+ common/tuklib_cpucores.c
+ common/tuklib_cpucores.h
common/tuklib_integer.h
liblzma/check/check.c
liblzma/check/crc32_fast.c
@@ -91,14 +100,17 @@ SET(LZMA_SRCS
liblzma/common/filter_encoder.c
liblzma/common/filter_flags_decoder.c
liblzma/common/filter_flags_encoder.c
+ liblzma/common/hardware_cputhreads.c
liblzma/common/index.c
liblzma/common/index_decoder.c
liblzma/common/index_encoder.c
liblzma/common/index_hash.c
+ liblzma/common/outqueue.c
liblzma/common/stream_buffer_decoder.c
liblzma/common/stream_buffer_encoder.c
liblzma/common/stream_decoder.c
liblzma/common/stream_encoder.c
+ liblzma/common/stream_encoder_mt.c
liblzma/common/stream_flags_common.c
liblzma/common/stream_flags_decoder.c
liblzma/common/stream_flags_encoder.c
@@ -148,7 +160,7 @@ INCLUDE_DIRECTORIES(
# Disable warnings to avoid changing 3rd party code.
IF(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmliblzma/common/mythread.h b/Utilities/cmliblzma/common/mythread.h
new file mode 100644
index 000000000..be2265424
--- /dev/null
+++ b/Utilities/cmliblzma/common/mythread.h
@@ -0,0 +1,521 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file mythread.h
+/// \brief Some threading related helper macros and functions
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef MYTHREAD_H
+#define MYTHREAD_H
+
+#include "sysdefs.h"
+
+// If any type of threading is enabled, #define MYTHREAD_ENABLED.
+#if defined(MYTHREAD_POSIX) || defined(MYTHREAD_WIN95) \
+ || defined(MYTHREAD_VISTA)
+# define MYTHREAD_ENABLED 1
+#endif
+
+
+#ifdef MYTHREAD_ENABLED
+
+////////////////////////////////////////
+// Shared between all threading types //
+////////////////////////////////////////
+
+// Locks a mutex for a duration of a block.
+//
+// Perform mythread_mutex_lock(&mutex) in the beginning of a block
+// and mythread_mutex_unlock(&mutex) at the end of the block. "break"
+// may be used to unlock the mutex and jump out of the block.
+// mythread_sync blocks may be nested.
+//
+// Example:
+//
+// mythread_sync(mutex) {
+// foo();
+// if (some_error)
+// break; // Skips bar()
+// bar();
+// }
+//
+// At least GCC optimizes the loops completely away so it doesn't slow
+// things down at all compared to plain mythread_mutex_lock(&mutex)
+// and mythread_mutex_unlock(&mutex) calls.
+//
+#define mythread_sync(mutex) mythread_sync_helper1(mutex, __LINE__)
+#define mythread_sync_helper1(mutex, line) mythread_sync_helper2(mutex, line)
+#define mythread_sync_helper2(mutex, line) \
+ for (unsigned int mythread_i_ ## line = 0; \
+ mythread_i_ ## line \
+ ? (mythread_mutex_unlock(&(mutex)), 0) \
+ : (mythread_mutex_lock(&(mutex)), 1); \
+ mythread_i_ ## line = 1) \
+ for (unsigned int mythread_j_ ## line = 0; \
+ !mythread_j_ ## line; \
+ mythread_j_ ## line = 1)
+#endif
+
+
+#if !defined(MYTHREAD_ENABLED)
+
+//////////////////
+// No threading //
+//////////////////
+
+// Calls the given function once. This isn't thread safe.
+#define mythread_once(func) \
+do { \
+ static bool once_ = false; \
+ if (!once_) { \
+ func(); \
+ once_ = true; \
+ } \
+} while (0)
+
+
+#if !(defined(_WIN32) && !defined(__CYGWIN__))
+// Use sigprocmask() to set the signal mask in single-threaded programs.
+#include <signal.h>
+
+static inline void
+mythread_sigmask(int how, const sigset_t *restrict set,
+ sigset_t *restrict oset)
+{
+ int ret = sigprocmask(how, set, oset);
+ assert(ret == 0);
+ (void)ret;
+}
+#endif
+
+
+#elif defined(MYTHREAD_POSIX)
+
+////////////////////
+// Using pthreads //
+////////////////////
+
+#include <sys/time.h>
+#include <pthread.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+
+#define MYTHREAD_RET_TYPE void *
+#define MYTHREAD_RET_VALUE NULL
+
+typedef pthread_t mythread;
+typedef pthread_mutex_t mythread_mutex;
+
+typedef struct {
+ pthread_cond_t cond;
+#ifdef HAVE_CLOCK_GETTIME
+ // Clock ID (CLOCK_REALTIME or CLOCK_MONOTONIC) associated with
+ // the condition variable.
+ clockid_t clk_id;
+#endif
+} mythread_cond;
+
+typedef struct timespec mythread_condtime;
+
+
+// Calls the given function once in a thread-safe way.
+#define mythread_once(func) \
+ do { \
+ static pthread_once_t once_ = PTHREAD_ONCE_INIT; \
+ pthread_once(&once_, &func); \
+ } while (0)
+
+
+// Use pthread_sigmask() to set the signal mask in multi-threaded programs.
+// Do nothing on OpenVMS since it lacks pthread_sigmask().
+static inline void
+mythread_sigmask(int how, const sigset_t *restrict set,
+ sigset_t *restrict oset)
+{
+#ifdef __VMS
+ (void)how;
+ (void)set;
+ (void)oset;
+#else
+ int ret = pthread_sigmask(how, set, oset);
+ assert(ret == 0);
+ (void)ret;
+#endif
+}
+
+
+// Creates a new thread with all signals blocked. Returns zero on success
+// and non-zero on error.
+static inline int
+mythread_create(mythread *thread, void *(*func)(void *arg), void *arg)
+{
+ sigset_t old;
+ sigset_t all;
+ sigfillset(&all);
+
+ mythread_sigmask(SIG_SETMASK, &all, &old);
+ const int ret = pthread_create(thread, NULL, func, arg);
+ mythread_sigmask(SIG_SETMASK, &old, NULL);
+
+ return ret;
+}
+
+// Joins a thread. Returns zero on success and non-zero on error.
+static inline int
+mythread_join(mythread thread)
+{
+ return pthread_join(thread, NULL);
+}
+
+
+// Initiatlizes a mutex. Returns zero on success and non-zero on error.
+static inline int
+mythread_mutex_init(mythread_mutex *mutex)
+{
+ return pthread_mutex_init(mutex, NULL);
+}
+
+static inline void
+mythread_mutex_destroy(mythread_mutex *mutex)
+{
+ int ret = pthread_mutex_destroy(mutex);
+ assert(ret == 0);
+ (void)ret;
+}
+
+static inline void
+mythread_mutex_lock(mythread_mutex *mutex)
+{
+ int ret = pthread_mutex_lock(mutex);
+ assert(ret == 0);
+ (void)ret;
+}
+
+static inline void
+mythread_mutex_unlock(mythread_mutex *mutex)
+{
+ int ret = pthread_mutex_unlock(mutex);
+ assert(ret == 0);
+ (void)ret;
+}
+
+
+// Initializes a condition variable.
+//
+// Using CLOCK_MONOTONIC instead of the default CLOCK_REALTIME makes the
+// timeout in pthread_cond_timedwait() work correctly also if system time
+// is suddenly changed. Unfortunately CLOCK_MONOTONIC isn't available
+// everywhere while the default CLOCK_REALTIME is, so the default is
+// used if CLOCK_MONOTONIC isn't available.
+//
+// If clock_gettime() isn't available at all, gettimeofday() will be used.
+static inline int
+mythread_cond_init(mythread_cond *mycond)
+{
+#ifdef HAVE_CLOCK_GETTIME
+ // NOTE: HAVE_DECL_CLOCK_MONOTONIC is always defined to 0 or 1.
+# if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && HAVE_DECL_CLOCK_MONOTONIC
+ struct timespec ts;
+ pthread_condattr_t condattr;
+
+ // POSIX doesn't seem to *require* that pthread_condattr_setclock()
+ // will fail if given an unsupported clock ID. Test that
+ // CLOCK_MONOTONIC really is supported using clock_gettime().
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0
+ && pthread_condattr_init(&condattr) == 0) {
+ int ret = pthread_condattr_setclock(
+ &condattr, CLOCK_MONOTONIC);
+ if (ret == 0)
+ ret = pthread_cond_init(&mycond->cond, &condattr);
+
+ pthread_condattr_destroy(&condattr);
+
+ if (ret == 0) {
+ mycond->clk_id = CLOCK_MONOTONIC;
+ return 0;
+ }
+ }
+
+ // If anything above fails, fall back to the default CLOCK_REALTIME.
+ // POSIX requires that all implementations of clock_gettime() must
+ // support at least CLOCK_REALTIME.
+# endif
+
+ mycond->clk_id = CLOCK_REALTIME;
+#endif
+
+ return pthread_cond_init(&mycond->cond, NULL);
+}
+
+static inline void
+mythread_cond_destroy(mythread_cond *cond)
+{
+ int ret = pthread_cond_destroy(&cond->cond);
+ assert(ret == 0);
+ (void)ret;
+}
+
+static inline void
+mythread_cond_signal(mythread_cond *cond)
+{
+ int ret = pthread_cond_signal(&cond->cond);
+ assert(ret == 0);
+ (void)ret;
+}
+
+static inline void
+mythread_cond_wait(mythread_cond *cond, mythread_mutex *mutex)
+{
+ int ret = pthread_cond_wait(&cond->cond, mutex);
+ assert(ret == 0);
+ (void)ret;
+}
+
+// Waits on a condition or until a timeout expires. If the timeout expires,
+// non-zero is returned, otherwise zero is returned.
+static inline int
+mythread_cond_timedwait(mythread_cond *cond, mythread_mutex *mutex,
+ const mythread_condtime *condtime)
+{
+ int ret = pthread_cond_timedwait(&cond->cond, mutex, condtime);
+ assert(ret == 0 || ret == ETIMEDOUT);
+ return ret;
+}
+
+// Sets condtime to the absolute time that is timeout_ms milliseconds
+// in the future. The type of the clock to use is taken from cond.
+static inline void
+mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond,
+ uint32_t timeout_ms)
+{
+ condtime->tv_sec = timeout_ms / 1000;
+ condtime->tv_nsec = (timeout_ms % 1000) * 1000000;
+
+#ifdef HAVE_CLOCK_GETTIME
+ struct timespec now;
+ int ret = clock_gettime(cond->clk_id, &now);
+ assert(ret == 0);
+ (void)ret;
+
+ condtime->tv_sec += now.tv_sec;
+ condtime->tv_nsec += now.tv_nsec;
+#else
+ (void)cond;
+
+ struct timeval now;
+ gettimeofday(&now, NULL);
+
+ condtime->tv_sec += now.tv_sec;
+ condtime->tv_nsec += now.tv_usec * 1000L;
+#endif
+
+ // tv_nsec must stay in the range [0, 999_999_999].
+ if (condtime->tv_nsec >= 1000000000L) {
+ condtime->tv_nsec -= 1000000000L;
+ ++condtime->tv_sec;
+ }
+}
+
+
+#elif defined(MYTHREAD_WIN95) || defined(MYTHREAD_VISTA)
+
+/////////////////////
+// Windows threads //
+/////////////////////
+
+#define WIN32_LEAN_AND_MEAN
+#ifdef MYTHREAD_VISTA
+# undef _WIN32_WINNT
+# define _WIN32_WINNT 0x0600
+#endif
+#include <windows.h>
+#include <process.h>
+
+#define MYTHREAD_RET_TYPE unsigned int __stdcall
+#define MYTHREAD_RET_VALUE 0
+
+typedef HANDLE mythread;
+typedef CRITICAL_SECTION mythread_mutex;
+
+#ifdef MYTHREAD_WIN95
+typedef HANDLE mythread_cond;
+#else
+typedef CONDITION_VARIABLE mythread_cond;
+#endif
+
+typedef struct {
+ // Tick count (milliseconds) in the beginning of the timeout.
+ // NOTE: This is 32 bits so it wraps around after 49.7 days.
+ // Multi-day timeouts may not work as expected.
+ DWORD start;
+
+ // Length of the timeout in milliseconds. The timeout expires
+ // when the current tick count minus "start" is equal or greater
+ // than "timeout".
+ DWORD timeout;
+} mythread_condtime;
+
+
+// mythread_once() is only available with Vista threads.
+#ifdef MYTHREAD_VISTA
+#define mythread_once(func) \
+ do { \
+ static INIT_ONCE once_ = INIT_ONCE_STATIC_INIT; \
+ BOOL pending_; \
+ if (!InitOnceBeginInitialize(&once_, 0, &pending_, NULL)) \
+ abort(); \
+ if (pending_) \
+ func(); \
+ if (!InitOnceComplete(&once, 0, NULL)) \
+ abort(); \
+ } while (0)
+#endif
+
+
+// mythread_sigmask() isn't available on Windows. Even a dummy version would
+// make no sense because the other POSIX signal functions are missing anyway.
+
+
+static inline int
+mythread_create(mythread *thread,
+ unsigned int (__stdcall *func)(void *arg), void *arg)
+{
+ uintptr_t ret = _beginthreadex(NULL, 0, func, arg, 0, NULL);
+ if (ret == 0)
+ return -1;
+
+ *thread = (HANDLE)ret;
+ return 0;
+}
+
+static inline int
+mythread_join(mythread thread)
+{
+ int ret = 0;
+
+ if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0)
+ ret = -1;
+
+ if (!CloseHandle(thread))
+ ret = -1;
+
+ return ret;
+}
+
+
+static inline int
+mythread_mutex_init(mythread_mutex *mutex)
+{
+ InitializeCriticalSection(mutex);
+ return 0;
+}
+
+static inline void
+mythread_mutex_destroy(mythread_mutex *mutex)
+{
+ DeleteCriticalSection(mutex);
+}
+
+static inline void
+mythread_mutex_lock(mythread_mutex *mutex)
+{
+ EnterCriticalSection(mutex);
+}
+
+static inline void
+mythread_mutex_unlock(mythread_mutex *mutex)
+{
+ LeaveCriticalSection(mutex);
+}
+
+
+static inline int
+mythread_cond_init(mythread_cond *cond)
+{
+#ifdef MYTHREAD_WIN95
+ *cond = CreateEvent(NULL, FALSE, FALSE, NULL);
+ return *cond == NULL ? -1 : 0;
+#else
+ InitializeConditionVariable(cond);
+ return 0;
+#endif
+}
+
+static inline void
+mythread_cond_destroy(mythread_cond *cond)
+{
+#ifdef MYTHREAD_WIN95
+ CloseHandle(*cond);
+#else
+ (void)cond;
+#endif
+}
+
+static inline void
+mythread_cond_signal(mythread_cond *cond)
+{
+#ifdef MYTHREAD_WIN95
+ SetEvent(*cond);
+#else
+ WakeConditionVariable(cond);
+#endif
+}
+
+static inline void
+mythread_cond_wait(mythread_cond *cond, mythread_mutex *mutex)
+{
+#ifdef MYTHREAD_WIN95
+ LeaveCriticalSection(mutex);
+ WaitForSingleObject(*cond, INFINITE);
+ EnterCriticalSection(mutex);
+#else
+ BOOL ret = SleepConditionVariableCS(cond, mutex, INFINITE);
+ assert(ret);
+ (void)ret;
+#endif
+}
+
+static inline int
+mythread_cond_timedwait(mythread_cond *cond, mythread_mutex *mutex,
+ const mythread_condtime *condtime)
+{
+#ifdef MYTHREAD_WIN95
+ LeaveCriticalSection(mutex);
+#endif
+
+ DWORD elapsed = GetTickCount() - condtime->start;
+ DWORD timeout = elapsed >= condtime->timeout
+ ? 0 : condtime->timeout - elapsed;
+
+#ifdef MYTHREAD_WIN95
+ DWORD ret = WaitForSingleObject(*cond, timeout);
+ assert(ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT);
+
+ EnterCriticalSection(mutex);
+
+ return ret == WAIT_TIMEOUT;
+#else
+ BOOL ret = SleepConditionVariableCS(cond, mutex, timeout);
+ assert(ret || GetLastError() == ERROR_TIMEOUT);
+ return !ret;
+#endif
+}
+
+static inline void
+mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond,
+ uint32_t timeout)
+{
+ (void)cond;
+ condtime->start = GetTickCount();
+ condtime->timeout = timeout;
+}
+
+#endif
+
+#endif
diff --git a/Utilities/cmliblzma/common/sysdefs.h b/Utilities/cmliblzma/common/sysdefs.h
index 22f487b9e..86c5da0d6 100644
--- a/Utilities/cmliblzma/common/sysdefs.h
+++ b/Utilities/cmliblzma/common/sysdefs.h
@@ -49,9 +49,7 @@
// Some pre-C99 systems have SIZE_MAX in limits.h instead of stdint.h. The
// limits are also used to figure out some macros missing from pre-C99 systems.
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
+#include <limits.h>
#if defined(_MSC_VER) && (_MSC_VER < 1310)
@@ -164,9 +162,7 @@ typedef unsigned char _Bool;
// string.h should be enough but let's include strings.h and memory.h too if
// they exists, since that shouldn't do any harm, but may improve portability.
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
+#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
@@ -204,7 +200,8 @@ typedef unsigned char _Bool;
# define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
#endif
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
+#if defined(__GNUC__) \
+ && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4)
# define lzma_attr_alloc_size(x) __attribute__((__alloc_size__(x)))
#else
# define lzma_attr_alloc_size(x)
diff --git a/Utilities/cmliblzma/common/tuklib_common.h b/Utilities/cmliblzma/common/tuklib_common.h
new file mode 100644
index 000000000..31fbab58b
--- /dev/null
+++ b/Utilities/cmliblzma/common/tuklib_common.h
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file tuklib_common.h
+/// \brief Common definitions for tuklib modules
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_COMMON_H
+#define TUKLIB_COMMON_H
+
+// The config file may be replaced by a package-specific file.
+// It should include at least stddef.h, inttypes.h, and limits.h.
+#include "tuklib_config.h"
+
+// TUKLIB_SYMBOL_PREFIX is prefixed to all symbols exported by
+// the tuklib modules. If you use a tuklib module in a library,
+// you should use TUKLIB_SYMBOL_PREFIX to make sure that there
+// are no symbol conflicts in case someone links your library
+// into application that also uses the same tuklib module.
+#ifndef TUKLIB_SYMBOL_PREFIX
+# define TUKLIB_SYMBOL_PREFIX
+#endif
+
+#define TUKLIB_CAT_X(a, b) a ## b
+#define TUKLIB_CAT(a, b) TUKLIB_CAT_X(a, b)
+
+#ifndef TUKLIB_SYMBOL
+# define TUKLIB_SYMBOL(sym) TUKLIB_CAT(TUKLIB_SYMBOL_PREFIX, sym)
+#endif
+
+#ifndef TUKLIB_DECLS_BEGIN
+# ifdef __cplusplus
+# define TUKLIB_DECLS_BEGIN extern "C" {
+# else
+# define TUKLIB_DECLS_BEGIN
+# endif
+#endif
+
+#ifndef TUKLIB_DECLS_END
+# ifdef __cplusplus
+# define TUKLIB_DECLS_END }
+# else
+# define TUKLIB_DECLS_END
+# endif
+#endif
+
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define TUKLIB_GNUC_REQ(major, minor) \
+ ((__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)) \
+ || __GNUC__ > (major))
+#else
+# define TUKLIB_GNUC_REQ(major, minor) 0
+#endif
+
+#if TUKLIB_GNUC_REQ(2, 5)
+# define tuklib_attr_noreturn __attribute__((__noreturn__))
+#else
+# define tuklib_attr_noreturn
+#endif
+
+#if (defined(_WIN32) && !defined(__CYGWIN__)) \
+ || defined(__OS2__) || defined(__MSDOS__)
+# define TUKLIB_DOSLIKE 1
+#endif
+
+#endif
diff --git a/Utilities/cmliblzma/common/tuklib_config.h b/Utilities/cmliblzma/common/tuklib_config.h
new file mode 100644
index 000000000..549cb24d7
--- /dev/null
+++ b/Utilities/cmliblzma/common/tuklib_config.h
@@ -0,0 +1,7 @@
+#ifdef HAVE_CONFIG_H
+# include "sysdefs.h"
+#else
+# include <stddef.h>
+# include <inttypes.h>
+# include <limits.h>
+#endif
diff --git a/Utilities/cmliblzma/common/tuklib_cpucores.c b/Utilities/cmliblzma/common/tuklib_cpucores.c
new file mode 100644
index 000000000..cc968dd25
--- /dev/null
+++ b/Utilities/cmliblzma/common/tuklib_cpucores.c
@@ -0,0 +1,100 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file tuklib_cpucores.c
+/// \brief Get the number of CPU cores online
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tuklib_cpucores.h"
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0500
+# endif
+# include <windows.h>
+
+// glibc >= 2.9
+#elif defined(TUKLIB_CPUCORES_SCHED_GETAFFINITY)
+# include <sched.h>
+
+// FreeBSD
+#elif defined(TUKLIB_CPUCORES_CPUSET)
+# include <sys/param.h>
+# include <sys/cpuset.h>
+
+#elif defined(TUKLIB_CPUCORES_SYSCTL)
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# endif
+# include <sys/sysctl.h>
+
+#elif defined(TUKLIB_CPUCORES_SYSCONF)
+# include <unistd.h>
+
+// HP-UX
+#elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
+# include <sys/param.h>
+# include <sys/pstat.h>
+#endif
+
+
+extern uint32_t
+tuklib_cpucores(void)
+{
+ uint32_t ret = 0;
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ ret = sysinfo.dwNumberOfProcessors;
+
+#elif defined(TUKLIB_CPUCORES_SCHED_GETAFFINITY)
+ cpu_set_t cpu_mask;
+ if (sched_getaffinity(0, sizeof(cpu_mask), &cpu_mask) == 0)
+ ret = (uint32_t)CPU_COUNT(&cpu_mask);
+
+#elif defined(TUKLIB_CPUCORES_CPUSET)
+ cpuset_t set;
+ if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
+ sizeof(set), &set) == 0) {
+# ifdef CPU_COUNT
+ ret = (uint32_t)CPU_COUNT(&set);
+# else
+ for (unsigned i = 0; i < CPU_SETSIZE; ++i)
+ if (CPU_ISSET(i, &set))
+ ++ret;
+# endif
+ }
+
+#elif defined(TUKLIB_CPUCORES_SYSCTL)
+ int name[2] = { CTL_HW, HW_NCPU };
+ int cpus;
+ size_t cpus_size = sizeof(cpus);
+ if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1
+ && cpus_size == sizeof(cpus) && cpus > 0)
+ ret = (uint32_t)cpus;
+
+#elif defined(TUKLIB_CPUCORES_SYSCONF)
+# ifdef _SC_NPROCESSORS_ONLN
+ // Most systems
+ const long cpus = sysconf(_SC_NPROCESSORS_ONLN);
+# else
+ // IRIX
+ const long cpus = sysconf(_SC_NPROC_ONLN);
+# endif
+ if (cpus > 0)
+ ret = (uint32_t)cpus;
+
+#elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
+ struct pst_dynamic pst;
+ if (pstat_getdynamic(&pst, sizeof(pst), 1, 0) != -1)
+ ret = (uint32_t)pst.psd_proc_cnt;
+#endif
+
+ return ret;
+}
diff --git a/Utilities/cmliblzma/common/tuklib_cpucores.h b/Utilities/cmliblzma/common/tuklib_cpucores.h
new file mode 100644
index 000000000..be1ce1c17
--- /dev/null
+++ b/Utilities/cmliblzma/common/tuklib_cpucores.h
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file tuklib_cpucores.h
+/// \brief Get the number of CPU cores online
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_CPUCORES_H
+#define TUKLIB_CPUCORES_H
+
+#include "tuklib_common.h"
+TUKLIB_DECLS_BEGIN
+
+#define tuklib_cpucores TUKLIB_SYMBOL(tuklib_cpucores)
+extern uint32_t tuklib_cpucores(void);
+
+TUKLIB_DECLS_END
+#endif
diff --git a/Utilities/cmliblzma/common/tuklib_integer.h b/Utilities/cmliblzma/common/tuklib_integer.h
index 5d8268580..4e613575e 100644
--- a/Utilities/cmliblzma/common/tuklib_integer.h
+++ b/Utilities/cmliblzma/common/tuklib_integer.h
@@ -6,22 +6,26 @@
/// This file provides macros or functions to do some basic integer and bit
/// operations.
///
-/// Endianness related integer operations (XX = 16, 32, or 64; Y = b or l):
-/// - Byte swapping: bswapXX(num)
-/// - Byte order conversions to/from native: convXXYe(num)
-/// - Aligned reads: readXXYe(ptr)
-/// - Aligned writes: writeXXYe(ptr, num)
-/// - Unaligned reads (16/32-bit only): unaligned_readXXYe(ptr)
-/// - Unaligned writes (16/32-bit only): unaligned_writeXXYe(ptr, num)
+/// Native endian inline functions (XX = 16, 32, or 64):
+/// - Unaligned native endian reads: readXXne(ptr)
+/// - Unaligned native endian writes: writeXXne(ptr, num)
+/// - Aligned native endian reads: aligned_readXXne(ptr)
+/// - Aligned native endian writes: aligned_writeXXne(ptr, num)
///
-/// Since they can macros, the arguments should have no side effects since
-/// they may be evaluated more than once.
+/// Endianness-converting integer operations (these can be macros!)
+/// (XX = 16, 32, or 64; Y = b or l):
+/// - Byte swapping: bswapXX(num)
+/// - Byte order conversions to/from native (byteswaps if Y isn't
+/// the native endianness): convXXYe(num)
+/// - Unaligned reads (16/32-bit only): readXXYe(ptr)
+/// - Unaligned writes (16/32-bit only): writeXXYe(ptr, num)
+/// - Aligned reads: aligned_readXXYe(ptr)
+/// - Aligned writes: aligned_writeXXYe(ptr, num)
///
-/// \todo PowerPC and possibly some other architectures support
-/// byte swapping load and store instructions. This file
-/// doesn't take advantage of those instructions.
+/// Since the above can macros, the arguments should have no side effects
+/// because they may be evaluated more than once.
///
-/// Bit scan operations for non-zero 32-bit integers:
+/// Bit scan operations for non-zero 32-bit integers (inline functions):
/// - Bit scan reverse (find highest non-zero bit): bsr32(num)
/// - Count leading zeros: clz32(num)
/// - Count trailing zeros: ctz32(num)
@@ -41,22 +45,27 @@
#ifndef TUKLIB_INTEGER_H
#define TUKLIB_INTEGER_H
-#include "sysdefs.h"
+#include "tuklib_common.h"
+#include <string.h>
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-# define TUKLIB_GNUC_REQ(major, minor) \
- ((__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)) \
- || __GNUC__ > (major))
-#else
-# define TUKLIB_GNUC_REQ(major, minor) 0
+// Newer Intel C compilers require immintrin.h for _bit_scan_reverse()
+// and such functions.
+#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)
+# include <immintrin.h>
#endif
-////////////////////////////////////////
-// Operating system specific features //
-////////////////////////////////////////
+///////////////////
+// Byte swapping //
+///////////////////
+
+#if defined(HAVE___BUILTIN_BSWAPXX)
+ // GCC >= 4.8 and Clang
+# define bswap16(n) __builtin_bswap16(n)
+# define bswap32(n) __builtin_bswap32(n)
+# define bswap64(n) __builtin_bswap64(n)
-#if defined(HAVE_BYTESWAP_H)
+#elif defined(HAVE_BYTESWAP_H)
// glibc, uClibc, dietlibc
# include <byteswap.h>
# ifdef HAVE_BSWAP_16
@@ -105,45 +114,33 @@
# endif
#endif
-
-////////////////////////////////
-// Compiler-specific features //
-////////////////////////////////
-
-// Newer Intel C compilers require immintrin.h for _bit_scan_reverse()
-// and such functions.
-#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)
-# include <immintrin.h>
-#endif
-
-
-///////////////////
-// Byte swapping //
-///////////////////
-
#ifndef bswap16
-# define bswap16(num) \
- (((uint16_t)(num) << 8) | ((uint16_t)(num) >> 8))
+# define bswap16(n) (uint16_t)( \
+ (((n) & 0x00FFU) << 8) \
+ | (((n) & 0xFF00U) >> 8) \
+ )
#endif
#ifndef bswap32
-# define bswap32(num) \
- ( (((uint32_t)(num) << 24) ) \
- | (((uint32_t)(num) << 8) & UINT32_C(0x00FF0000)) \
- | (((uint32_t)(num) >> 8) & UINT32_C(0x0000FF00)) \
- | (((uint32_t)(num) >> 24) ) )
+# define bswap32(n) (uint32_t)( \
+ (((n) & UINT32_C(0x000000FF)) << 24) \
+ | (((n) & UINT32_C(0x0000FF00)) << 8) \
+ | (((n) & UINT32_C(0x00FF0000)) >> 8) \
+ | (((n) & UINT32_C(0xFF000000)) >> 24) \
+ )
#endif
#ifndef bswap64
-# define bswap64(num) \
- ( (((uint64_t)(num) << 56) ) \
- | (((uint64_t)(num) << 40) & UINT64_C(0x00FF000000000000)) \
- | (((uint64_t)(num) << 24) & UINT64_C(0x0000FF0000000000)) \
- | (((uint64_t)(num) << 8) & UINT64_C(0x000000FF00000000)) \
- | (((uint64_t)(num) >> 8) & UINT64_C(0x00000000FF000000)) \
- | (((uint64_t)(num) >> 24) & UINT64_C(0x0000000000FF0000)) \
- | (((uint64_t)(num) >> 40) & UINT64_C(0x000000000000FF00)) \
- | (((uint64_t)(num) >> 56) ) )
+# define bswap64(n) (uint64_t)( \
+ (((n) & UINT64_C(0x00000000000000FF)) << 56) \
+ | (((n) & UINT64_C(0x000000000000FF00)) << 40) \
+ | (((n) & UINT64_C(0x0000000000FF0000)) << 24) \
+ | (((n) & UINT64_C(0x00000000FF000000)) << 8) \
+ | (((n) & UINT64_C(0x000000FF00000000)) >> 8) \
+ | (((n) & UINT64_C(0x0000FF0000000000)) >> 24) \
+ | (((n) & UINT64_C(0x00FF000000000000)) >> 40) \
+ | (((n) & UINT64_C(0xFF00000000000000)) >> 56) \
+ )
#endif
// Define conversion macros using the basic byte swapping macros.
@@ -188,76 +185,76 @@
#endif
-//////////////////////////////
-// Aligned reads and writes //
-//////////////////////////////
-
-static inline uint16_t
-read16be(const uint8_t *buf)
-{
- uint16_t num = *(const uint16_t *)buf;
- return conv16be(num);
-}
+////////////////////////////////
+// Unaligned reads and writes //
+////////////////////////////////
+// The traditional way of casting e.g. *(const uint16_t *)uint8_pointer
+// is bad even if the uint8_pointer is properly aligned because this kind
+// of casts break strict aliasing rules and result in undefined behavior.
+// With unaligned pointers it's even worse: compilers may emit vector
+// instructions that require aligned pointers even if non-vector
+// instructions work with unaligned pointers.
+//
+// Using memcpy() is the standard compliant way to do unaligned access.
+// Many modern compilers inline it so there is no function call overhead.
+// For those compilers that don't handle the memcpy() method well, the
+// old casting method (that violates strict aliasing) can be requested at
+// build time. A third method, casting to a packed struct, would also be
+// an option but isn't provided to keep things simpler (it's already a mess).
+// Hopefully this is flexible enough in practice.
static inline uint16_t
-read16le(const uint8_t *buf)
+read16ne(const uint8_t *buf)
{
- uint16_t num = *(const uint16_t *)buf;
- return conv16le(num);
-}
-
-
-static inline uint32_t
-read32be(const uint8_t *buf)
-{
- uint32_t num = *(const uint32_t *)buf;
- return conv32be(num);
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING)
+ return *(const uint16_t *)buf;
+#else
+ uint16_t num;
+ memcpy(&num, buf, sizeof(num));
+ return num;
+#endif
}
static inline uint32_t
-read32le(const uint8_t *buf)
-{
- uint32_t num = *(const uint32_t *)buf;
- return conv32le(num);
-}
-
-
-static inline uint64_t
-read64be(const uint8_t *buf)
+read32ne(const uint8_t *buf)
{
- uint64_t num = *(const uint64_t *)buf;
- return conv64be(num);
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING)
+ return *(const uint32_t *)buf;
+#else
+ uint32_t num;
+ memcpy(&num, buf, sizeof(num));
+ return num;
+#endif
}
static inline uint64_t
-read64le(const uint8_t *buf)
+read64ne(const uint8_t *buf)
{
- uint64_t num = *(const uint64_t *)buf;
- return conv64le(num);
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING)
+ return *(const uint64_t *)buf;
+#else
+ uint64_t num;
+ memcpy(&num, buf, sizeof(num));
+ return num;
+#endif
}
-// NOTE: Possible byte swapping must be done in a macro to allow GCC
-// to optimize byte swapping of constants when using glibc's or *BSD's
-// byte swapping macros. The actual write is done in an inline function
-// to make type checking of the buf pointer possible similarly to readXXYe()
-// functions.
-
-#define write16be(buf, num) write16ne((buf), conv16be(num))
-#define write16le(buf, num) write16ne((buf), conv16le(num))
-#define write32be(buf, num) write32ne((buf), conv32be(num))
-#define write32le(buf, num) write32ne((buf), conv32le(num))
-#define write64be(buf, num) write64ne((buf), conv64be(num))
-#define write64le(buf, num) write64ne((buf), conv64le(num))
-
-
static inline void
write16ne(uint8_t *buf, uint16_t num)
{
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING)
*(uint16_t *)buf = num;
+#else
+ memcpy(buf, &num, sizeof(num));
+#endif
return;
}
@@ -265,7 +262,12 @@ write16ne(uint8_t *buf, uint16_t num)
static inline void
write32ne(uint8_t *buf, uint32_t num)
{
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING)
*(uint32_t *)buf = num;
+#else
+ memcpy(buf, &num, sizeof(num));
+#endif
return;
}
@@ -273,90 +275,114 @@ write32ne(uint8_t *buf, uint32_t num)
static inline void
write64ne(uint8_t *buf, uint64_t num)
{
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING)
*(uint64_t *)buf = num;
+#else
+ memcpy(buf, &num, sizeof(num));
+#endif
return;
}
-////////////////////////////////
-// Unaligned reads and writes //
-////////////////////////////////
-
-// NOTE: TUKLIB_FAST_UNALIGNED_ACCESS indicates only support for 16-bit and
-// 32-bit unaligned integer loads and stores. It's possible that 64-bit
-// unaligned access doesn't work or is slower than byte-by-byte access.
-// Since unaligned 64-bit is probably not needed as often as 16-bit or
-// 32-bit, we simply don't support 64-bit unaligned access for now.
-#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
-# define unaligned_read16be read16be
-# define unaligned_read16le read16le
-# define unaligned_read32be read32be
-# define unaligned_read32le read32le
-# define unaligned_write16be write16be
-# define unaligned_write16le write16le
-# define unaligned_write32be write32be
-# define unaligned_write32le write32le
-
-#else
-
static inline uint16_t
-unaligned_read16be(const uint8_t *buf)
+read16be(const uint8_t *buf)
{
+#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS)
+ uint16_t num = read16ne(buf);
+ return conv16be(num);
+#else
uint16_t num = ((uint16_t)buf[0] << 8) | (uint16_t)buf[1];
return num;
+#endif
}
static inline uint16_t
-unaligned_read16le(const uint8_t *buf)
+read16le(const uint8_t *buf)
{
+#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS)
+ uint16_t num = read16ne(buf);
+ return conv16le(num);
+#else
uint16_t num = ((uint16_t)buf[0]) | ((uint16_t)buf[1] << 8);
return num;
+#endif
}
static inline uint32_t
-unaligned_read32be(const uint8_t *buf)
+read32be(const uint8_t *buf)
{
+#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS)
+ uint32_t num = read32ne(buf);
+ return conv32be(num);
+#else
uint32_t num = (uint32_t)buf[0] << 24;
num |= (uint32_t)buf[1] << 16;
num |= (uint32_t)buf[2] << 8;
num |= (uint32_t)buf[3];
return num;
+#endif
}
static inline uint32_t
-unaligned_read32le(const uint8_t *buf)
+read32le(const uint8_t *buf)
{
+#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS)
+ uint32_t num = read32ne(buf);
+ return conv32le(num);
+#else
uint32_t num = (uint32_t)buf[0];
num |= (uint32_t)buf[1] << 8;
num |= (uint32_t)buf[2] << 16;
num |= (uint32_t)buf[3] << 24;
return num;
+#endif
}
+// NOTE: Possible byte swapping must be done in a macro to allow the compiler
+// to optimize byte swapping of constants when using glibc's or *BSD's
+// byte swapping macros. The actual write is done in an inline function
+// to make type checking of the buf pointer possible.
+#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS)
+# define write16be(buf, num) write16ne(buf, conv16be(num))
+# define write32be(buf, num) write32ne(buf, conv32be(num))
+#endif
+
+#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS)
+# define write16le(buf, num) write16ne(buf, conv16le(num))
+# define write32le(buf, num) write32ne(buf, conv32le(num))
+#endif
+
+
+#ifndef write16be
static inline void
-unaligned_write16be(uint8_t *buf, uint16_t num)
+write16be(uint8_t *buf, uint16_t num)
{
buf[0] = (uint8_t)(num >> 8);
buf[1] = (uint8_t)num;
return;
}
+#endif
+#ifndef write16le
static inline void
-unaligned_write16le(uint8_t *buf, uint16_t num)
+write16le(uint8_t *buf, uint16_t num)
{
buf[0] = (uint8_t)num;
buf[1] = (uint8_t)(num >> 8);
return;
}
+#endif
+#ifndef write32be
static inline void
-unaligned_write32be(uint8_t *buf, uint32_t num)
+write32be(uint8_t *buf, uint32_t num)
{
buf[0] = (uint8_t)(num >> 24);
buf[1] = (uint8_t)(num >> 16);
@@ -364,10 +390,12 @@ unaligned_write32be(uint8_t *buf, uint32_t num)
buf[3] = (uint8_t)num;
return;
}
+#endif
+#ifndef write32le
static inline void
-unaligned_write32le(uint8_t *buf, uint32_t num)
+write32le(uint8_t *buf, uint32_t num)
{
buf[0] = (uint8_t)num;
buf[1] = (uint8_t)(num >> 8);
@@ -375,10 +403,184 @@ unaligned_write32le(uint8_t *buf, uint32_t num)
buf[3] = (uint8_t)(num >> 24);
return;
}
+#endif
+
+
+//////////////////////////////
+// Aligned reads and writes //
+//////////////////////////////
+// Separate functions for aligned reads and writes are provided since on
+// strict-align archs aligned access is much faster than unaligned access.
+//
+// Just like in the unaligned case, memcpy() is needed to avoid
+// strict aliasing violations. However, on archs that don't support
+// unaligned access the compiler cannot know that the pointers given
+// to memcpy() are aligned which results in slow code. As of C11 there is
+// no standard way to tell the compiler that we know that the address is
+// aligned but some compilers have language extensions to do that. With
+// such language extensions the memcpy() method gives excellent results.
+//
+// What to do on a strict-align system when no known language extentensions
+// are available? Falling back to byte-by-byte access would be safe but ruin
+// optimizations that have been made specifically with aligned access in mind.
+// As a compromise, aligned reads will fall back to non-compliant type punning
+// but aligned writes will be byte-by-byte, that is, fast reads are preferred
+// over fast writes. This obviously isn't great but hopefully it's a working
+// compromise for now.
+//
+// __builtin_assume_aligned is support by GCC >= 4.7 and clang >= 3.6.
+#ifdef HAVE___BUILTIN_ASSUME_ALIGNED
+# define tuklib_memcpy_aligned(dest, src, size) \
+ memcpy(dest, __builtin_assume_aligned(src, size), size)
+#else
+# define tuklib_memcpy_aligned(dest, src, size) \
+ memcpy(dest, src, size)
+# ifndef TUKLIB_FAST_UNALIGNED_ACCESS
+# define TUKLIB_USE_UNSAFE_ALIGNED_READS 1
+# endif
#endif
+static inline uint16_t
+aligned_read16ne(const uint8_t *buf)
+{
+#if defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) \
+ || defined(TUKLIB_USE_UNSAFE_ALIGNED_READS)
+ return *(const uint16_t *)buf;
+#else
+ uint16_t num;
+ tuklib_memcpy_aligned(&num, buf, sizeof(num));
+ return num;
+#endif
+}
+
+
+static inline uint32_t
+aligned_read32ne(const uint8_t *buf)
+{
+#if defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) \
+ || defined(TUKLIB_USE_UNSAFE_ALIGNED_READS)
+ return *(const uint32_t *)buf;
+#else
+ uint32_t num;
+ tuklib_memcpy_aligned(&num, buf, sizeof(num));
+ return num;
+#endif
+}
+
+
+static inline uint64_t
+aligned_read64ne(const uint8_t *buf)
+{
+#if defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) \
+ || defined(TUKLIB_USE_UNSAFE_ALIGNED_READS)
+ return *(const uint64_t *)buf;
+#else
+ uint64_t num;
+ tuklib_memcpy_aligned(&num, buf, sizeof(num));
+ return num;
+#endif
+}
+
+
+static inline void
+aligned_write16ne(uint8_t *buf, uint16_t num)
+{
+#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING
+ *(uint16_t *)buf = num;
+#else
+ tuklib_memcpy_aligned(buf, &num, sizeof(num));
+#endif
+ return;
+}
+
+
+static inline void
+aligned_write32ne(uint8_t *buf, uint32_t num)
+{
+#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING
+ *(uint32_t *)buf = num;
+#else
+ tuklib_memcpy_aligned(buf, &num, sizeof(num));
+#endif
+ return;
+}
+
+
+static inline void
+aligned_write64ne(uint8_t *buf, uint64_t num)
+{
+#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING
+ *(uint64_t *)buf = num;
+#else
+ tuklib_memcpy_aligned(buf, &num, sizeof(num));
+#endif
+ return;
+}
+
+
+static inline uint16_t
+aligned_read16be(const uint8_t *buf)
+{
+ uint16_t num = aligned_read16ne(buf);
+ return conv16be(num);
+}
+
+
+static inline uint16_t
+aligned_read16le(const uint8_t *buf)
+{
+ uint16_t num = aligned_read16ne(buf);
+ return conv16le(num);
+}
+
+
+static inline uint32_t
+aligned_read32be(const uint8_t *buf)
+{
+ uint32_t num = aligned_read32ne(buf);
+ return conv32be(num);
+}
+
+
+static inline uint32_t
+aligned_read32le(const uint8_t *buf)
+{
+ uint32_t num = aligned_read32ne(buf);
+ return conv32le(num);
+}
+
+
+static inline uint64_t
+aligned_read64be(const uint8_t *buf)
+{
+ uint64_t num = aligned_read64ne(buf);
+ return conv64be(num);
+}
+
+
+static inline uint64_t
+aligned_read64le(const uint8_t *buf)
+{
+ uint64_t num = aligned_read64ne(buf);
+ return conv64le(num);
+}
+
+
+// These need to be macros like in the unaligned case.
+#define aligned_write16be(buf, num) aligned_write16ne((buf), conv16be(num))
+#define aligned_write16le(buf, num) aligned_write16ne((buf), conv16le(num))
+#define aligned_write32be(buf, num) aligned_write32ne((buf), conv32be(num))
+#define aligned_write32le(buf, num) aligned_write32ne((buf), conv32le(num))
+#define aligned_write64be(buf, num) aligned_write64ne((buf), conv64be(num))
+#define aligned_write64le(buf, num) aligned_write64ne((buf), conv64le(num))
+
+
+////////////////////
+// Bit operations //
+////////////////////
+
static inline uint32_t
bsr32(uint32_t n)
{
@@ -391,7 +593,7 @@ bsr32(uint32_t n)
// multiple architectures. On x86, __builtin_clz() ^ 31U becomes
// either plain BSR (so the XOR gets optimized away) or LZCNT and
// XOR (if -march indicates that SSE4a instructions are supported).
- return __builtin_clz(n) ^ 31U;
+ return (uint32_t)__builtin_clz(n) ^ 31U;
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
uint32_t i;
@@ -401,27 +603,27 @@ bsr32(uint32_t n)
#else
uint32_t i = 31;
- if ((n & UINT32_C(0xFFFF0000)) == 0) {
+ if ((n & 0xFFFF0000) == 0) {
n <<= 16;
i = 15;
}
- if ((n & UINT32_C(0xFF000000)) == 0) {
+ if ((n & 0xFF000000) == 0) {
n <<= 8;
i -= 8;
}
- if ((n & UINT32_C(0xF0000000)) == 0) {
+ if ((n & 0xF0000000) == 0) {
n <<= 4;
i -= 4;
}
- if ((n & UINT32_C(0xC0000000)) == 0) {
+ if ((n & 0xC0000000) == 0) {
n <<= 2;
i -= 2;
}
- if ((n & UINT32_C(0x80000000)) == 0)
+ if ((n & 0x80000000) == 0)
--i;
return i;
@@ -436,7 +638,7 @@ clz32(uint32_t n)
return _bit_scan_reverse(n) ^ 31U;
#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
- return __builtin_clz(n);
+ return (uint32_t)__builtin_clz(n);
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
uint32_t i;
@@ -448,27 +650,27 @@ clz32(uint32_t n)
#else
uint32_t i = 0;
- if ((n & UINT32_C(0xFFFF0000)) == 0) {
+ if ((n & 0xFFFF0000) == 0) {
n <<= 16;
i = 16;
}
- if ((n & UINT32_C(0xFF000000)) == 0) {
+ if ((n & 0xFF000000) == 0) {
n <<= 8;
i += 8;
}
- if ((n & UINT32_C(0xF0000000)) == 0) {
+ if ((n & 0xF0000000) == 0) {
n <<= 4;
i += 4;
}
- if ((n & UINT32_C(0xC0000000)) == 0) {
+ if ((n & 0xC0000000) == 0) {
n <<= 2;
i += 2;
}
- if ((n & UINT32_C(0x80000000)) == 0)
+ if ((n & 0x80000000) == 0)
++i;
return i;
@@ -483,7 +685,7 @@ ctz32(uint32_t n)
return _bit_scan_forward(n);
#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX >= UINT32_MAX
- return __builtin_ctz(n);
+ return (uint32_t)__builtin_ctz(n);
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
uint32_t i;
@@ -493,27 +695,27 @@ ctz32(uint32_t n)
#else
uint32_t i = 0;
- if ((n & UINT32_C(0x0000FFFF)) == 0) {
+ if ((n & 0x0000FFFF) == 0) {
n >>= 16;
i = 16;
}
- if ((n & UINT32_C(0x000000FF)) == 0) {
+ if ((n & 0x000000FF) == 0) {
n >>= 8;
i += 8;
}
- if ((n & UINT32_C(0x0000000F)) == 0) {
+ if ((n & 0x0000000F) == 0) {
n >>= 4;
i += 4;
}
- if ((n & UINT32_C(0x00000003)) == 0) {
+ if ((n & 0x00000003) == 0) {
n >>= 2;
i += 2;
}
- if ((n & UINT32_C(0x00000001)) == 0)
+ if ((n & 0x00000001) == 0)
++i;
return i;
diff --git a/Utilities/cmliblzma/liblzma/api/lzma.h b/Utilities/cmliblzma/liblzma/api/lzma.h
index aa88e4243..122dab80d 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma.h
@@ -224,7 +224,8 @@
# else
# define lzma_nothrow throw()
# endif
-# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+# elif defined(__GNUC__) && (__GNUC__ > 3 \
+ || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
# define lzma_nothrow __attribute__((__nothrow__))
# else
# define lzma_nothrow
@@ -241,7 +242,7 @@
* break anything if these are sometimes enabled and sometimes not, only
* affects warnings and optimizations.
*/
-#if __GNUC__ >= 3
+#if defined(__GNUC__) && __GNUC__ >= 3
# ifndef lzma_attribute
# define lzma_attribute(attr) __attribute__(attr)
# endif
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/block.h b/Utilities/cmliblzma/liblzma/api/lzma/block.h
index 7bdcfd7cb..962f38779 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/block.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/block.h
@@ -448,7 +448,7 @@ extern LZMA_API(lzma_vli) lzma_block_total_size(const lzma_block *block)
* - LZMA_MEM_ERROR
* - LZMA_OPTIONS_ERROR
* - LZMA_UNSUPPORTED_CHECK: block->check specifies a Check ID
- * that is not supported by this buid of liblzma. Initializing
+ * that is not supported by this build of liblzma. Initializing
* the encoder failed.
* - LZMA_PROG_ERROR
*/
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/filter.h b/Utilities/cmliblzma/liblzma/api/lzma/filter.h
index 4e78752b8..8c8593147 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/filter.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/filter.h
@@ -341,9 +341,10 @@ extern LZMA_API(lzma_ret) lzma_properties_encode(
* \param filter filter->id must have been set to the correct
* Filter ID. filter->options doesn't need to be
* initialized (it's not freed by this function). The
- * decoded options will be stored to filter->options.
- * filter->options is set to NULL if there are no
- * properties or if an error occurs.
+ * decoded options will be stored in filter->options;
+ * it's application's responsibility to free it when
+ * appropriate. filter->options is set to NULL if
+ * there are no properties or if an error occurs.
* \param allocator Custom memory allocator used to allocate the
* options. Set to NULL to use the default malloc(),
* and in case of an error, also free().
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/hardware.h b/Utilities/cmliblzma/liblzma/api/lzma/hardware.h
index 5321d9af8..47481f258 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/hardware.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/hardware.h
@@ -6,7 +6,7 @@
* ways to limit the resource usage. Applications linking against liblzma
* need to do the actual decisions how much resources to let liblzma to use.
* To ease making these decisions, liblzma provides functions to find out
- * the relevant capabilities of the underlaying hardware. Currently there
+ * the relevant capabilities of the underlying hardware. Currently there
* is only a function to find out the amount of RAM, but in the future there
* will be also a function to detect how many concurrent threads the system
* can run.
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/lzma12.h b/Utilities/cmliblzma/liblzma/api/lzma/lzma12.h
index 4e32fa3a2..df5f23b61 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/lzma12.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/lzma12.h
@@ -301,7 +301,7 @@ typedef struct {
* (2^ pb =2^2=4), which is often a good choice when there's
* no better guess.
*
- * When the aligment is known, setting pb accordingly may reduce
+ * When the alignment is known, setting pb accordingly may reduce
* the file size a little. E.g. with text files having one-byte
* alignment (US-ASCII, ISO-8859-*, UTF-8), setting pb=0 can
* improve compression slightly. For UTF-16 text, pb=1 is a good
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/version.h b/Utilities/cmliblzma/liblzma/api/lzma/version.h
index 143c7dea6..2bf3eaed2 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/version.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/version.h
@@ -22,7 +22,7 @@
*/
#define LZMA_VERSION_MAJOR 5
#define LZMA_VERSION_MINOR 2
-#define LZMA_VERSION_PATCH 4
+#define LZMA_VERSION_PATCH 5
#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE
#ifndef LZMA_VERSION_COMMIT
diff --git a/Utilities/cmliblzma/liblzma/api/lzma/vli.h b/Utilities/cmliblzma/liblzma/api/lzma/vli.h
index 9ad13f2e2..1b7a952a4 100644
--- a/Utilities/cmliblzma/liblzma/api/lzma/vli.h
+++ b/Utilities/cmliblzma/liblzma/api/lzma/vli.h
@@ -54,7 +54,7 @@
*
* Valid VLI values are in the range [0, LZMA_VLI_MAX]. Unknown value is
* indicated with LZMA_VLI_UNKNOWN, which is the maximum value of the
- * underlaying integer type.
+ * underlying integer type.
*
* lzma_vli will be uint64_t for the foreseeable future. If a bigger size
* is needed in the future, it is guaranteed that 2 * LZMA_VLI_MAX will
diff --git a/Utilities/cmliblzma/liblzma/check/crc32_fast.c b/Utilities/cmliblzma/liblzma/check/crc32_fast.c
index 3de02638d..eed735058 100644
--- a/Utilities/cmliblzma/liblzma/check/crc32_fast.c
+++ b/Utilities/cmliblzma/liblzma/check/crc32_fast.c
@@ -49,7 +49,7 @@ lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
// Calculate the CRC32 using the slice-by-eight algorithm.
while (buf < limit) {
- crc ^= *(const uint32_t *)(buf);
+ crc ^= aligned_read32ne(buf);
buf += 4;
crc = lzma_crc32_table[7][A(crc)]
@@ -57,7 +57,7 @@ lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
^ lzma_crc32_table[5][C(crc)]
^ lzma_crc32_table[4][D(crc)];
- const uint32_t tmp = *(const uint32_t *)(buf);
+ const uint32_t tmp = aligned_read32ne(buf);
buf += 4;
// At least with some compilers, it is critical for
diff --git a/Utilities/cmliblzma/liblzma/check/crc32_table.c b/Utilities/cmliblzma/liblzma/check/crc32_table.c
index 368874eb7..b11762ae0 100644
--- a/Utilities/cmliblzma/liblzma/check/crc32_table.c
+++ b/Utilities/cmliblzma/liblzma/check/crc32_table.c
@@ -12,6 +12,9 @@
#include "common.h"
+// Having the declaration here silences clang -Wmissing-variable-declarations.
+extern const uint32_t lzma_crc32_table[8][256];
+
#ifdef WORDS_BIGENDIAN
# include "crc32_table_be.h"
#else
diff --git a/Utilities/cmliblzma/liblzma/check/crc64_fast.c b/Utilities/cmliblzma/liblzma/check/crc64_fast.c
index 52af29ed4..8af54cda7 100644
--- a/Utilities/cmliblzma/liblzma/check/crc64_fast.c
+++ b/Utilities/cmliblzma/liblzma/check/crc64_fast.c
@@ -47,9 +47,9 @@ lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
while (buf < limit) {
#ifdef WORDS_BIGENDIAN
const uint32_t tmp = (crc >> 32)
- ^ *(const uint32_t *)(buf);
+ ^ aligned_read32ne(buf);
#else
- const uint32_t tmp = crc ^ *(const uint32_t *)(buf);
+ const uint32_t tmp = crc ^ aligned_read32ne(buf);
#endif
buf += 4;
diff --git a/Utilities/cmliblzma/liblzma/check/crc64_table.c b/Utilities/cmliblzma/liblzma/check/crc64_table.c
index 1fbcd9470..7560eb0a3 100644
--- a/Utilities/cmliblzma/liblzma/check/crc64_table.c
+++ b/Utilities/cmliblzma/liblzma/check/crc64_table.c
@@ -12,6 +12,9 @@
#include "common.h"
+// Having the declaration here silences clang -Wmissing-variable-declarations.
+extern const uint64_t lzma_crc64_table[4][256];
+
#ifdef WORDS_BIGENDIAN
# include "crc64_table_be.h"
#else
diff --git a/Utilities/cmliblzma/liblzma/common/alone_decoder.c b/Utilities/cmliblzma/liblzma/common/alone_decoder.c
index 77d0a9b10..239b230ef 100644
--- a/Utilities/cmliblzma/liblzma/common/alone_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/alone_decoder.c
@@ -50,8 +50,7 @@ typedef struct {
static lzma_ret
-alone_decode(void *coder_ptr,
- const lzma_allocator *allocator lzma_attribute((__unused__)),
+alone_decode(void *coder_ptr, const lzma_allocator *allocator,
const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size, uint8_t *restrict out,
size_t *restrict out_pos, size_t out_size,
diff --git a/Utilities/cmliblzma/liblzma/common/alone_encoder.c b/Utilities/cmliblzma/liblzma/common/alone_encoder.c
index 4853cfd1d..96c1db70c 100644
--- a/Utilities/cmliblzma/liblzma/common/alone_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/alone_encoder.c
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file alone_decoder.c
-/// \brief Decoder for LZMA_Alone files
+/// \file alone_encoder.c
+/// \brief Encoder for LZMA_Alone files
//
// Author: Lasse Collin
//
@@ -31,8 +31,7 @@ typedef struct {
static lzma_ret
-alone_encode(void *coder_ptr,
- const lzma_allocator *allocator lzma_attribute((__unused__)),
+alone_encode(void *coder_ptr, const lzma_allocator *allocator,
const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size, uint8_t *restrict out,
size_t *restrict out_pos, size_t out_size,
@@ -122,7 +121,7 @@ alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
if (d != UINT32_MAX)
++d;
- unaligned_write32le(coder->header + 1, d);
+ write32le(coder->header + 1, d);
// - Uncompressed size (always unknown and using EOPM)
memset(coder->header + 1 + 4, 0xFF, 8);
diff --git a/Utilities/cmliblzma/liblzma/common/block_header_decoder.c b/Utilities/cmliblzma/liblzma/common/block_header_decoder.c
index 1dd982f6b..2e1135dd6 100644
--- a/Utilities/cmliblzma/liblzma/common/block_header_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/block_header_decoder.c
@@ -67,7 +67,7 @@ lzma_block_header_decode(lzma_block *block,
const size_t in_size = block->header_size - 4;
// Verify CRC32
- if (lzma_crc32(in, in_size, 0) != unaligned_read32le(in + in_size))
+ if (lzma_crc32(in, in_size, 0) != read32le(in + in_size))
return LZMA_DATA_ERROR;
// Check for unsupported flags.
@@ -98,7 +98,7 @@ lzma_block_header_decode(lzma_block *block,
block->uncompressed_size = LZMA_VLI_UNKNOWN;
// Filter Flags
- const size_t filter_count = (in[1] & 3) + 1;
+ const size_t filter_count = (in[1] & 3U) + 1;
for (size_t i = 0; i < filter_count; ++i) {
const lzma_ret ret = lzma_filter_flags_decode(
&block->filters[i], allocator,
diff --git a/Utilities/cmliblzma/liblzma/common/block_header_encoder.c b/Utilities/cmliblzma/liblzma/common/block_header_encoder.c
index 5c5f5424a..160425d27 100644
--- a/Utilities/cmliblzma/liblzma/common/block_header_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/block_header_encoder.c
@@ -126,7 +126,7 @@ lzma_block_header_encode(const lzma_block *block, uint8_t *out)
memzero(out + out_pos, out_size - out_pos);
// CRC32
- unaligned_write32le(out + out_size, lzma_crc32(out, out_size, 0));
+ write32le(out + out_size, lzma_crc32(out, out_size, 0));
return LZMA_OK;
}
diff --git a/Utilities/cmliblzma/liblzma/common/block_util.c b/Utilities/cmliblzma/liblzma/common/block_util.c
index 00c7fe8d5..acb311142 100644
--- a/Utilities/cmliblzma/liblzma/common/block_util.c
+++ b/Utilities/cmliblzma/liblzma/common/block_util.c
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file block_header.c
+/// \file block_util.c
/// \brief Utility functions to handle lzma_block
//
// Author: Lasse Collin
diff --git a/Utilities/cmliblzma/liblzma/common/common.c b/Utilities/cmliblzma/liblzma/common/common.c
index 57e3f8ebd..cf714e5e4 100644
--- a/Utilities/cmliblzma/liblzma/common/common.c
+++ b/Utilities/cmliblzma/liblzma/common/common.c
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file common.h
+/// \file common.c
/// \brief Common functions needed in many places in liblzma
//
// Author: Lasse Collin
@@ -99,7 +99,11 @@ lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
const size_t out_avail = out_size - *out_pos;
const size_t copy_size = my_min(in_avail, out_avail);
- memcpy(out + *out_pos, in + *in_pos, copy_size);
+ // Call memcpy() only if there is something to copy. If there is
+ // nothing to copy, in or out might be NULL and then the memcpy()
+ // call would trigger undefined behavior.
+ if (copy_size > 0)
+ memcpy(out + *out_pos, in + *in_pos, copy_size);
*in_pos += copy_size;
*out_pos += copy_size;
diff --git a/Utilities/cmliblzma/liblzma/common/common.h b/Utilities/cmliblzma/liblzma/common/common.h
index dde3ae0ec..b3d3b7a05 100644
--- a/Utilities/cmliblzma/liblzma/common/common.h
+++ b/Utilities/cmliblzma/liblzma/common/common.h
@@ -14,6 +14,7 @@
#define LZMA_COMMON_H
#include "sysdefs.h"
+#include "mythread.h"
#include "tuklib_integer.h"
#if defined(_WIN32) || defined(__CYGWIN__)
diff --git a/Utilities/cmliblzma/liblzma/common/filter_common.h b/Utilities/cmliblzma/liblzma/common/filter_common.h
index 42a26a24a..9390305c2 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_common.h
+++ b/Utilities/cmliblzma/liblzma/common/filter_common.h
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file filter_common.c
+/// \file filter_common.h
/// \brief Filter-specific stuff common for both encoder and decoder
//
// Author: Lasse Collin
diff --git a/Utilities/cmliblzma/liblzma/common/filter_decoder.h b/Utilities/cmliblzma/liblzma/common/filter_decoder.h
index a2e255fe5..2dac60282 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_decoder.h
+++ b/Utilities/cmliblzma/liblzma/common/filter_decoder.h
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
-/// \file filter_decoder.c
+/// \file filter_decoder.h
/// \brief Filter ID mapping to filter-specific functions
//
// Author: Lasse Collin
diff --git a/Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c b/Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c
index d110566de..b57b9fd80 100644
--- a/Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file filter_flags_encoder.c
-/// \brief Decodes a Filter Flags field
+/// \brief Encodes a Filter Flags field
//
// Author: Lasse Collin
//
diff --git a/Utilities/cmliblzma/liblzma/common/hardware_physmem.c b/Utilities/cmliblzma/liblzma/common/hardware_physmem.c
index 7405b658a..a2bbbe29d 100644
--- a/Utilities/cmliblzma/liblzma/common/hardware_physmem.c
+++ b/Utilities/cmliblzma/liblzma/common/hardware_physmem.c
@@ -19,7 +19,7 @@ extern LZMA_API(uint64_t)
lzma_physmem(void)
{
// It is simpler to make lzma_physmem() a wrapper for
- // tuklib_physmem() than to hack appropriate symbol visiblity
+ // tuklib_physmem() than to hack appropriate symbol visibility
// support for the tuklib modules.
return tuklib_physmem();
}
diff --git a/Utilities/cmliblzma/liblzma/common/index.c b/Utilities/cmliblzma/liblzma/common/index.c
index 26e4e519b..a41e8f330 100644
--- a/Utilities/cmliblzma/liblzma/common/index.c
+++ b/Utilities/cmliblzma/liblzma/common/index.c
@@ -105,7 +105,7 @@ typedef struct {
typedef struct {
- /// Every index_stream is a node in the tree of Sreams.
+ /// Every index_stream is a node in the tree of Streams.
index_tree_node node;
/// Number of this Stream (first one is 1)
@@ -166,7 +166,7 @@ struct lzma_index_s {
lzma_vli index_list_size;
/// How many Records to allocate at once in lzma_index_append().
- /// This defaults to INDEX_GROUP_SIZE but can be overriden with
+ /// This defaults to INDEX_GROUP_SIZE but can be overridden with
/// lzma_index_prealloc().
size_t prealloc;
@@ -825,8 +825,8 @@ lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
s->groups.root = &newg->node;
}
- if (s->groups.rightmost == &g->node)
- s->groups.rightmost = &newg->node;
+ assert(s->groups.rightmost == &g->node);
+ s->groups.rightmost = &newg->node;
lzma_free(g, allocator);
diff --git a/Utilities/cmliblzma/liblzma/common/memcmplen.h b/Utilities/cmliblzma/liblzma/common/memcmplen.h
index c1efc9e28..dcfd8d6f8 100644
--- a/Utilities/cmliblzma/liblzma/common/memcmplen.h
+++ b/Utilities/cmliblzma/liblzma/common/memcmplen.h
@@ -61,8 +61,7 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
// to __builtin_clzll().
#define LZMA_MEMCMPLEN_EXTRA 8
while (len < limit) {
- const uint64_t x = *(const uint64_t *)(buf1 + len)
- - *(const uint64_t *)(buf2 + len);
+ const uint64_t x = read64ne(buf1 + len) - read64ne(buf2 + len);
if (x != 0) {
# if defined(_M_X64) // MSVC or Intel C compiler on Windows
unsigned long tmp;
@@ -99,15 +98,7 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
_mm_loadu_si128((const __m128i *)(buf2 + len))));
if (x != 0) {
-# if defined(__INTEL_COMPILER)
- len += _bit_scan_forward(x);
-# elif defined(_MSC_VER)
- unsigned long tmp;
- _BitScanForward(&tmp, x);
- len += tmp;
-# else
- len += __builtin_ctz(x);
-# endif
+ len += ctz32(x);
return my_min(len, limit);
}
@@ -120,8 +111,7 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
// Generic 32-bit little endian method
# define LZMA_MEMCMPLEN_EXTRA 4
while (len < limit) {
- uint32_t x = *(const uint32_t *)(buf1 + len)
- - *(const uint32_t *)(buf2 + len);
+ uint32_t x = read32ne(buf1 + len) - read32ne(buf2 + len);
if (x != 0) {
if ((x & 0xFFFF) == 0) {
len += 2;
@@ -143,8 +133,7 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
// Generic 32-bit big endian method
# define LZMA_MEMCMPLEN_EXTRA 4
while (len < limit) {
- uint32_t x = *(const uint32_t *)(buf1 + len)
- ^ *(const uint32_t *)(buf2 + len);
+ uint32_t x = read32ne(buf1 + len) ^ read32ne(buf2 + len);
if (x != 0) {
if ((x & 0xFFFF0000) == 0) {
len += 2;
diff --git a/Utilities/cmliblzma/liblzma/common/stream_encoder_mt.c b/Utilities/cmliblzma/liblzma/common/stream_encoder_mt.c
index 2efe44c25..01e403397 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_encoder_mt.c
+++ b/Utilities/cmliblzma/liblzma/common/stream_encoder_mt.c
@@ -700,7 +700,7 @@ stream_encode_mt(void *coder_ptr, const lzma_allocator *allocator,
ret = coder->thread_error;
if (ret != LZMA_OK) {
assert(ret != LZMA_STREAM_END);
- break;
+ break; // Break out of mythread_sync.
}
// Try to read compressed data to out[].
@@ -958,7 +958,7 @@ stream_encoder_mt_init(lzma_next_coder *next, const lzma_allocator *allocator,
// Validate the filter chain so that we can give an error in this
// function instead of delaying it to the first call to lzma_code().
// The memory usage calculation verifies the filter chain as
- // a side effect so we take advatange of that.
+ // a side effect so we take advantage of that.
if (lzma_raw_encoder_memusage(filters) == UINT64_MAX)
return LZMA_OPTIONS_ERROR;
diff --git a/Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c b/Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c
index 1bc2f97c5..4e43e359e 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/stream_flags_decoder.c
@@ -38,7 +38,7 @@ lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in)
// and unsupported files.
const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic),
LZMA_STREAM_FLAGS_SIZE, 0);
- if (crc != unaligned_read32le(in + sizeof(lzma_header_magic)
+ if (crc != read32le(in + sizeof(lzma_header_magic)
+ LZMA_STREAM_FLAGS_SIZE))
return LZMA_DATA_ERROR;
@@ -67,7 +67,7 @@ lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in)
// CRC32
const uint32_t crc = lzma_crc32(in + sizeof(uint32_t),
sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0);
- if (crc != unaligned_read32le(in))
+ if (crc != read32le(in))
return LZMA_DATA_ERROR;
// Stream Flags
@@ -75,7 +75,7 @@ lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in)
return LZMA_OPTIONS_ERROR;
// Backward Size
- options->backward_size = unaligned_read32le(in + sizeof(uint32_t));
+ options->backward_size = read32le(in + sizeof(uint32_t));
options->backward_size = (options->backward_size + 1) * 4;
return LZMA_OK;
diff --git a/Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c b/Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c
index 4e717159f..b98ab17c4 100644
--- a/Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/stream_flags_encoder.c
@@ -46,8 +46,8 @@ lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out)
const uint32_t crc = lzma_crc32(out + sizeof(lzma_header_magic),
LZMA_STREAM_FLAGS_SIZE, 0);
- unaligned_write32le(out + sizeof(lzma_header_magic)
- + LZMA_STREAM_FLAGS_SIZE, crc);
+ write32le(out + sizeof(lzma_header_magic) + LZMA_STREAM_FLAGS_SIZE,
+ crc);
return LZMA_OK;
}
@@ -66,7 +66,7 @@ lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out)
if (!is_backward_size_valid(options))
return LZMA_PROG_ERROR;
- unaligned_write32le(out + 4, options->backward_size / 4 - 1);
+ write32le(out + 4, options->backward_size / 4 - 1);
// Stream Flags
if (stream_flags_encode(options, out + 2 * 4))
@@ -76,7 +76,7 @@ lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out)
const uint32_t crc = lzma_crc32(
out + 4, 4 + LZMA_STREAM_FLAGS_SIZE, 0);
- unaligned_write32le(out, crc);
+ write32le(out, crc);
// Magic
memcpy(out + 2 * 4 + LZMA_STREAM_FLAGS_SIZE,
diff --git a/Utilities/cmliblzma/liblzma/common/vli_decoder.c b/Utilities/cmliblzma/liblzma/common/vli_decoder.c
index c181828bf..af2799d1f 100644
--- a/Utilities/cmliblzma/liblzma/common/vli_decoder.c
+++ b/Utilities/cmliblzma/liblzma/common/vli_decoder.c
@@ -72,7 +72,7 @@ lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos,
// corrupt.
//
// If we need bigger integers in future, old versions liblzma
- // will confusingly indicate the file being corrupt istead of
+ // will confusingly indicate the file being corrupt instead of
// unsupported. I suppose it's still better this way, because
// in the foreseeable future (writing this in 2008) the only
// reason why files would appear having over 63-bit integers
diff --git a/Utilities/cmliblzma/liblzma/delta/delta_decoder.c b/Utilities/cmliblzma/liblzma/delta/delta_decoder.c
index 6859afa5c..13d8a28f0 100644
--- a/Utilities/cmliblzma/liblzma/delta/delta_decoder.c
+++ b/Utilities/cmliblzma/liblzma/delta/delta_decoder.c
@@ -70,7 +70,7 @@ lzma_delta_props_decode(void **options, const lzma_allocator *allocator,
return LZMA_MEM_ERROR;
opt->type = LZMA_DELTA_TYPE_BYTE;
- opt->dist = props[0] + 1;
+ opt->dist = props[0] + 1U;
*options = opt;
diff --git a/Utilities/cmliblzma/liblzma/lz/lz_decoder.c b/Utilities/cmliblzma/liblzma/lz/lz_decoder.c
index c7086440b..09b574388 100644
--- a/Utilities/cmliblzma/liblzma/lz/lz_decoder.c
+++ b/Utilities/cmliblzma/liblzma/lz/lz_decoder.c
@@ -91,11 +91,17 @@ decode_buffer(lzma_coder *coder,
in, in_pos, in_size);
// Copy the decoded data from the dictionary to the out[]
- // buffer.
+ // buffer. Do it conditionally because out can be NULL
+ // (in which case copy_size is always 0). Calling memcpy()
+ // with a null-pointer is undefined even if the third
+ // argument is 0.
const size_t copy_size = coder->dict.pos - dict_start;
assert(copy_size <= out_size - *out_pos);
- memcpy(out + *out_pos, coder->dict.buf + dict_start,
- copy_size);
+
+ if (copy_size > 0)
+ memcpy(out + *out_pos, coder->dict.buf + dict_start,
+ copy_size);
+
*out_pos += copy_size;
// Reset the dictionary if so requested by coder->lz.code().
@@ -125,8 +131,7 @@ decode_buffer(lzma_coder *coder,
static lzma_ret
-lz_decode(void *coder_ptr,
- const lzma_allocator *allocator lzma_attribute((__unused__)),
+lz_decode(void *coder_ptr, const lzma_allocator *allocator,
const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size, uint8_t *restrict out,
size_t *restrict out_pos, size_t out_size,
@@ -241,7 +246,7 @@ lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
if (lz_options.dict_size < 4096)
lz_options.dict_size = 4096;
- // Make dictionary size a multipe of 16. Some LZ-based decoders like
+ // Make dictionary size a multiple of 16. Some LZ-based decoders like
// LZMA use the lowest bits lzma_dict.pos to know the alignment of the
// data. Aligned buffer is also good when memcpying from the
// dictionary to the output buffer, since applications are
diff --git a/Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h b/Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h
index 342a333d1..fb15c5814 100644
--- a/Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h
+++ b/Utilities/cmliblzma/liblzma/lz/lz_encoder_hash.h
@@ -39,7 +39,7 @@
// Endianness doesn't matter in hash_2_calc() (no effect on the output).
#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
# define hash_2_calc() \
- const uint32_t hash_value = *(const uint16_t *)(cur)
+ const uint32_t hash_value = read16ne(cur)
#else
# define hash_2_calc() \
const uint32_t hash_value \
diff --git a/Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c b/Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c
index 78520779f..d03657a7c 100644
--- a/Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c
+++ b/Utilities/cmliblzma/liblzma/lz/lz_encoder_mf.c
@@ -113,7 +113,7 @@ normalize(lzma_mf *mf)
// may be match finders that use larger resolution than one byte.
const uint32_t subvalue
= (MUST_NORMALIZE_POS - mf->cyclic_size);
- // & (~(UINT32_C(1) << 10) - 1);
+ // & ~((UINT32_C(1) << 10) - 1);
for (uint32_t i = 0; i < mf->hash_count; ++i) {
// If the distance is greater than the dictionary size,
diff --git a/Utilities/cmliblzma/liblzma/lzma/fastpos.h b/Utilities/cmliblzma/liblzma/lzma/fastpos.h
index a3feea58d..cba442c27 100644
--- a/Utilities/cmliblzma/liblzma/lzma/fastpos.h
+++ b/Utilities/cmliblzma/liblzma/lzma/fastpos.h
@@ -101,7 +101,7 @@ extern const uint8_t lzma_fastpos[1 << FASTPOS_BITS];
(UINT32_C(1) << (FASTPOS_BITS + fastpos_shift(extra, n)))
#define fastpos_result(dist, extra, n) \
- lzma_fastpos[(dist) >> fastpos_shift(extra, n)] \
+ (uint32_t)(lzma_fastpos[(dist) >> fastpos_shift(extra, n)]) \
+ 2 * fastpos_shift(extra, n)
diff --git a/Utilities/cmliblzma/liblzma/lzma/fastpos_tablegen.c b/Utilities/cmliblzma/liblzma/lzma/fastpos_tablegen.c
index c97e6f411..d4484c82d 100644
--- a/Utilities/cmliblzma/liblzma/lzma/fastpos_tablegen.c
+++ b/Utilities/cmliblzma/liblzma/lzma/fastpos_tablegen.c
@@ -11,7 +11,6 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include <sys/types.h>
#include <inttypes.h>
#include <stdio.h>
#include "fastpos.h"
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c b/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c
index 878c870ae..cf1b5110a 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma2_decoder.c
@@ -136,7 +136,7 @@ lzma2_decode(void *coder_ptr, lzma_dict *restrict dict,
break;
case SEQ_UNCOMPRESSED_2:
- coder->uncompressed_size += in[(*in_pos)++] + 1;
+ coder->uncompressed_size += in[(*in_pos)++] + 1U;
coder->sequence = SEQ_COMPRESSED_0;
coder->lzma.set_uncompressed(coder->lzma.coder,
coder->uncompressed_size);
@@ -148,7 +148,7 @@ lzma2_decode(void *coder_ptr, lzma_dict *restrict dict,
break;
case SEQ_COMPRESSED_1:
- coder->compressed_size += in[(*in_pos)++] + 1;
+ coder->compressed_size += in[(*in_pos)++] + 1U;
coder->sequence = coder->next_sequence;
break;
@@ -297,8 +297,8 @@ lzma_lzma2_props_decode(void **options, const lzma_allocator *allocator,
if (props[0] == 40) {
opt->dict_size = UINT32_MAX;
} else {
- opt->dict_size = 2 | (props[0] & 1);
- opt->dict_size <<= props[0] / 2 + 11;
+ opt->dict_size = 2 | (props[0] & 1U);
+ opt->dict_size <<= props[0] / 2U + 11;
}
opt->preset_dict = NULL;
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_common.h b/Utilities/cmliblzma/liblzma/lzma/lzma_common.h
index 09efd3872..9d040d95b 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_common.h
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_common.h
@@ -122,7 +122,8 @@ typedef enum {
/// byte; and
/// - the highest literal_context_bits bits of the previous byte.
#define literal_subcoder(probs, lc, lp_mask, pos, prev_byte) \
- ((probs)[(((pos) & lp_mask) << lc) + ((prev_byte) >> (8 - lc))])
+ ((probs)[(((pos) & (lp_mask)) << (lc)) \
+ + ((uint32_t)(prev_byte) >> (8U - (lc)))])
static inline void
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c b/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c
index d0f29b763..e605a0a91 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_decoder.c
@@ -398,7 +398,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
// ("match byte") to "len" to minimize the
// number of variables we need to store
// between decoder calls.
- len = dict_get(&dict, rep0) << 1;
+ len = (uint32_t)(dict_get(&dict, rep0)) << 1;
// The usage of "offset" allows omitting some
// branches, which should give tiny speed
@@ -569,7 +569,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
#ifdef HAVE_SMALL
do {
rc_bit(probs[symbol], ,
- rep0 += 1 << offset,
+ rep0 += 1U << offset,
SEQ_DIST_MODEL);
} while (++offset < limit);
#else
@@ -577,25 +577,25 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
case 5:
assert(offset == 0);
rc_bit(probs[symbol], ,
- rep0 += 1,
+ rep0 += 1U,
SEQ_DIST_MODEL);
++offset;
--limit;
case 4:
rc_bit(probs[symbol], ,
- rep0 += 1 << offset,
+ rep0 += 1U << offset,
SEQ_DIST_MODEL);
++offset;
--limit;
case 3:
rc_bit(probs[symbol], ,
- rep0 += 1 << offset,
+ rep0 += 1U << offset,
SEQ_DIST_MODEL);
++offset;
--limit;
case 2:
rc_bit(probs[symbol], ,
- rep0 += 1 << offset,
+ rep0 += 1U << offset,
SEQ_DIST_MODEL);
++offset;
--limit;
@@ -607,7 +607,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
// the unneeded updating of
// "symbol".
rc_bit_last(probs[symbol], ,
- rep0 += 1 << offset,
+ rep0 += 1U << offset,
SEQ_DIST_MODEL);
}
#endif
@@ -635,7 +635,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
do {
rc_bit(coder->pos_align[
symbol], ,
- rep0 += 1 << offset,
+ rep0 += 1U << offset,
SEQ_ALIGN);
} while (++offset < ALIGN_BITS);
#else
@@ -1049,7 +1049,7 @@ lzma_lzma_props_decode(void **options, const lzma_allocator *allocator,
// All dictionary sizes are accepted, including zero. LZ decoder
// will automatically use a dictionary at least a few KiB even if
// a smaller dictionary is requested.
- opt->dict_size = unaligned_read32le(props + 1);
+ opt->dict_size = read32le(props + 1);
opt->preset_dict = NULL;
opt->preset_dict_size = 0;
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c
index ba9ce6989..07d2b87bc 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder.c
@@ -663,7 +663,7 @@ lzma_lzma_props_encode(const void *options, uint8_t *out)
if (lzma_lzma_lclppb_encode(opt, out))
return LZMA_PROG_ERROR;
- unaligned_write32le(out + 1, opt->dict_size);
+ write32le(out + 1, opt->dict_size);
return LZMA_OK;
}
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c
index 59f77343e..101c8d479 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c
@@ -636,9 +636,10 @@ helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf,
uint32_t len_test_2 = len_test + 1;
const uint32_t limit = my_min(buf_avail_full,
len_test_2 + nice_len);
- for (; len_test_2 < limit
- && buf[len_test_2] == buf_back[len_test_2];
- ++len_test_2) ;
+ // NOTE: len_test_2 may be greater than limit so the call to
+ // lzma_memcmplen() must be done conditionally.
+ if (len_test_2 < limit)
+ len_test_2 = lzma_memcmplen(buf, buf_back, len_test_2, limit);
len_test_2 -= len_test + 1;
@@ -732,9 +733,12 @@ helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf,
const uint32_t limit = my_min(buf_avail_full,
len_test_2 + nice_len);
- for (; len_test_2 < limit &&
- buf[len_test_2] == buf_back[len_test_2];
- ++len_test_2) ;
+ // NOTE: len_test_2 may be greater than limit
+ // so the call to lzma_memcmplen() must be
+ // done conditionally.
+ if (len_test_2 < limit)
+ len_test_2 = lzma_memcmplen(buf, buf_back,
+ len_test_2, limit);
len_test_2 -= len_test + 1;
diff --git a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h
index a2da969f4..2e34aace1 100644
--- a/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h
+++ b/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_private.h
@@ -25,8 +25,7 @@
// MATCH_LEN_MIN bytes. Unaligned access gives tiny gain so there's no
// reason to not use it when it is supported.
#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
-# define not_equal_16(a, b) \
- (*(const uint16_t *)(a) != *(const uint16_t *)(b))
+# define not_equal_16(a, b) (read16ne(a) != read16ne(b))
#else
# define not_equal_16(a, b) \
((a)[0] != (b)[0] || (a)[1] != (b)[1])
diff --git a/Utilities/cmliblzma/liblzma/simple/arm.c b/Utilities/cmliblzma/liblzma/simple/arm.c
index 181d0e3b2..ff5073ae5 100644
--- a/Utilities/cmliblzma/liblzma/simple/arm.c
+++ b/Utilities/cmliblzma/liblzma/simple/arm.c
@@ -22,9 +22,9 @@ arm_code(void *simple lzma_attribute((__unused__)),
size_t i;
for (i = 0; i + 4 <= size; i += 4) {
if (buffer[i + 3] == 0xEB) {
- uint32_t src = (buffer[i + 2] << 16)
- | (buffer[i + 1] << 8)
- | (buffer[i + 0]);
+ uint32_t src = ((uint32_t)(buffer[i + 2]) << 16)
+ | ((uint32_t)(buffer[i + 1]) << 8)
+ | (uint32_t)(buffer[i + 0]);
src <<= 2;
uint32_t dest;
diff --git a/Utilities/cmliblzma/liblzma/simple/armthumb.c b/Utilities/cmliblzma/liblzma/simple/armthumb.c
index eab4862dd..a8da334a0 100644
--- a/Utilities/cmliblzma/liblzma/simple/armthumb.c
+++ b/Utilities/cmliblzma/liblzma/simple/armthumb.c
@@ -23,10 +23,10 @@ armthumb_code(void *simple lzma_attribute((__unused__)),
for (i = 0; i + 4 <= size; i += 2) {
if ((buffer[i + 1] & 0xF8) == 0xF0
&& (buffer[i + 3] & 0xF8) == 0xF8) {
- uint32_t src = ((buffer[i + 1] & 0x7) << 19)
- | (buffer[i + 0] << 11)
- | ((buffer[i + 3] & 0x7) << 8)
- | (buffer[i + 2]);
+ uint32_t src = (((uint32_t)(buffer[i + 1]) & 7) << 19)
+ | ((uint32_t)(buffer[i + 0]) << 11)
+ | (((uint32_t)(buffer[i + 3]) & 7) << 8)
+ | (uint32_t)(buffer[i + 2]);
src <<= 1;
diff --git a/Utilities/cmliblzma/liblzma/simple/ia64.c b/Utilities/cmliblzma/liblzma/simple/ia64.c
index 580529e80..6492d0a38 100644
--- a/Utilities/cmliblzma/liblzma/simple/ia64.c
+++ b/Utilities/cmliblzma/liblzma/simple/ia64.c
@@ -70,7 +70,7 @@ ia64_code(void *simple lzma_attribute((__unused__)),
inst_norm |= (uint64_t)(dest & 0x100000)
<< (36 - 20);
- instruction &= (1 << bit_res) - 1;
+ instruction &= (1U << bit_res) - 1;
instruction |= (inst_norm << bit_res);
for (size_t j = 0; j < 6; j++)
diff --git a/Utilities/cmliblzma/liblzma/simple/powerpc.c b/Utilities/cmliblzma/liblzma/simple/powerpc.c
index 54dfbf102..0b60e9b3f 100644
--- a/Utilities/cmliblzma/liblzma/simple/powerpc.c
+++ b/Utilities/cmliblzma/liblzma/simple/powerpc.c
@@ -25,10 +25,11 @@ powerpc_code(void *simple lzma_attribute((__unused__)),
if ((buffer[i] >> 2) == 0x12
&& ((buffer[i + 3] & 3) == 1)) {
- const uint32_t src = ((buffer[i + 0] & 3) << 24)
- | (buffer[i + 1] << 16)
- | (buffer[i + 2] << 8)
- | (buffer[i + 3] & (~3));
+ const uint32_t src
+ = (((uint32_t)(buffer[i + 0]) & 3) << 24)
+ | ((uint32_t)(buffer[i + 1]) << 16)
+ | ((uint32_t)(buffer[i + 2]) << 8)
+ | ((uint32_t)(buffer[i + 3]) & ~UINT32_C(3));
uint32_t dest;
if (is_encoder)
diff --git a/Utilities/cmliblzma/liblzma/simple/simple_coder.c b/Utilities/cmliblzma/liblzma/simple/simple_coder.c
index 13ebabc76..4f499befe 100644
--- a/Utilities/cmliblzma/liblzma/simple/simple_coder.c
+++ b/Utilities/cmliblzma/liblzma/simple/simple_coder.c
@@ -118,7 +118,15 @@ simple_code(void *coder_ptr, const lzma_allocator *allocator,
// coder->pos and coder->size yet. This way the coder can be
// restarted if the next filter in the chain returns e.g.
// LZMA_MEM_ERROR.
- memcpy(out + *out_pos, coder->buffer + coder->pos, buf_avail);
+ //
+ // Do the memcpy() conditionally because out can be NULL
+ // (in which case buf_avail is always 0). Calling memcpy()
+ // with a null-pointer is undefined even if the third
+ // argument is 0.
+ if (buf_avail > 0)
+ memcpy(out + *out_pos, coder->buffer + coder->pos,
+ buf_avail);
+
*out_pos += buf_avail;
// Copy/Encode/Decode more data to out[].
diff --git a/Utilities/cmliblzma/liblzma/simple/simple_decoder.c b/Utilities/cmliblzma/liblzma/simple/simple_decoder.c
index 1d864f2bf..dc4d24151 100644
--- a/Utilities/cmliblzma/liblzma/simple/simple_decoder.c
+++ b/Utilities/cmliblzma/liblzma/simple/simple_decoder.c
@@ -28,7 +28,7 @@ lzma_simple_props_decode(void **options, const lzma_allocator *allocator,
if (opt == NULL)
return LZMA_MEM_ERROR;
- opt->start_offset = unaligned_read32le(props);
+ opt->start_offset = read32le(props);
// Don't leave an options structure allocated if start_offset is zero.
if (opt->start_offset == 0)
diff --git a/Utilities/cmliblzma/liblzma/simple/simple_encoder.c b/Utilities/cmliblzma/liblzma/simple/simple_encoder.c
index 8aa463bed..d2cc03e58 100644
--- a/Utilities/cmliblzma/liblzma/simple/simple_encoder.c
+++ b/Utilities/cmliblzma/liblzma/simple/simple_encoder.c
@@ -32,7 +32,7 @@ lzma_simple_props_encode(const void *options, uint8_t *out)
if (opt == NULL || opt->start_offset == 0)
return LZMA_OK;
- unaligned_write32le(out, opt->start_offset);
+ write32le(out, opt->start_offset);
return LZMA_OK;
}
diff --git a/Utilities/cmlibrhash/CMakeLists.txt b/Utilities/cmlibrhash/CMakeLists.txt
index 37e2399c4..1a01165c0 100644
--- a/Utilities/cmlibrhash/CMakeLists.txt
+++ b/Utilities/cmlibrhash/CMakeLists.txt
@@ -2,7 +2,7 @@ project(librhash C)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt
index f8b47af46..086345c8b 100644
--- a/Utilities/cmlibuv/CMakeLists.txt
+++ b/Utilities/cmlibuv/CMakeLists.txt
@@ -2,7 +2,7 @@ project(libuv C)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
@@ -156,7 +156,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS400")
)
endif()
-if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN")
+if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "MSYS")
list(APPEND uv_libraries
)
list(APPEND uv_headers
diff --git a/Utilities/cmnghttp2/CMakeLists.txt b/Utilities/cmnghttp2/CMakeLists.txt
index 17cc6ddb2..3bc2778ea 100644
--- a/Utilities/cmnghttp2/CMakeLists.txt
+++ b/Utilities/cmnghttp2/CMakeLists.txt
@@ -1,6 +1,6 @@
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmzlib/CMakeLists.txt b/Utilities/cmzlib/CMakeLists.txt
index d266af936..d57cb29a4 100644
--- a/Utilities/cmzlib/CMakeLists.txt
+++ b/Utilities/cmzlib/CMakeLists.txt
@@ -2,7 +2,7 @@ PROJECT(CMZLIB)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmzstd/CMakeLists.txt b/Utilities/cmzstd/CMakeLists.txt
index 323151c08..199719553 100644
--- a/Utilities/cmzstd/CMakeLists.txt
+++ b/Utilities/cmzstd/CMakeLists.txt
@@ -2,7 +2,7 @@ project(zstd C)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/std/cm/filesystem b/Utilities/std/cm/filesystem
index 6cbdea98a..ce52fbf3b 100644
--- a/Utilities/std/cm/filesystem
+++ b/Utilities/std/cm/filesystem
@@ -809,6 +809,10 @@ public:
path& remove_filename()
{
+# if defined(__CYGWIN__)
+ // FIXME: Avoid crash due to CYGWIN/MSYS bug(?). See CMake Issue 22090.
+ static_cast<void>(this->path_.data());
+# endif
auto fname = this->get_filename();
if (!fname.empty()) {
this->path_.erase(fname.data() - this->path_.data());
@@ -825,6 +829,10 @@ public:
path& replace_extension(const path& replacement = path())
{
+# if defined(__CYGWIN__)
+ // FIXME: Avoid crash due to CYGWIN/MSYS bug(?). See CMake Issue 22090.
+ static_cast<void>(this->path_.data());
+# endif
auto ext = this->get_filename_fragment(filename_fragment::extension);
if (!ext.empty()) {
this->path_.erase(ext.data() - this->path_.data());
diff --git a/bootstrap b/bootstrap
index f85d57ee3..dc5ed0b47 100755
--- a/bootstrap
+++ b/bootstrap
@@ -84,6 +84,7 @@ cmake_sphinx_info=""
cmake_sphinx_man=""
cmake_sphinx_html=""
cmake_sphinx_qthelp=""
+cmake_sphinx_latexpdf=""
cmake_sphinx_build=""
cmake_sphinx_flags=""
@@ -96,8 +97,17 @@ else
cmake_system_cygwin=false
fi
+# Determine whether this is a MSYS environment.
+if echo "${cmake_system}" | grep MSYS >/dev/null 2>&1; then
+ cmake_system_msys=true
+ cmake_doc_dir_keyword="MSYS"
+ cmake_man_dir_keyword="MSYS"
+else
+ cmake_system_msys=false
+fi
+
# Determine whether this is a MinGW environment.
-if echo "${cmake_system}" | grep 'MINGW\|MSYS' >/dev/null 2>&1; then
+if echo "${cmake_system}" | grep 'MINGW' >/dev/null 2>&1; then
cmake_system_mingw=true
else
cmake_system_mingw=false
@@ -377,6 +387,10 @@ CMAKE_CXX_SOURCES="\
cmInstallFilesCommand \
cmInstallFilesGenerator \
cmInstallGenerator \
+ cmInstallGetRuntimeDependenciesGenerator \
+ cmInstallImportedRuntimeArtifactsGenerator \
+ cmInstallRuntimeDependencySet \
+ cmInstallRuntimeDependencySetGenerator \
cmInstallScriptGenerator \
cmInstallSubdirectoryGenerator \
cmInstallTargetGenerator \
@@ -524,6 +538,7 @@ KWSYS_CXX_SOURCES="\
FStream \
Glob \
RegularExpression \
+ Status \
SystemTools"
KWSYS_FILES="\
@@ -534,6 +549,7 @@ KWSYS_FILES="\
Glob.hxx \
Process.h \
RegularExpression.hxx \
+ Status.hxx \
String.h \
String.hxx \
System.h \
@@ -662,6 +678,7 @@ Configuration:
--sphinx-man build man pages with Sphinx
--sphinx-html build html help with Sphinx
--sphinx-qthelp build qch help with Sphinx
+ --sphinx-latexpdf build PDF with Sphinx using LaTeX
--sphinx-build=<sb> use <sb> as the sphinx-build executable
--sphinx-flags=<flags> pass <flags> to sphinx-build executable
@@ -926,6 +943,7 @@ while test $# != 0; do
--sphinx-man) cmake_sphinx_man="1" ;;
--sphinx-html) cmake_sphinx_html="1" ;;
--sphinx-qthelp) cmake_sphinx_qthelp="1" ;;
+ --sphinx-latexpdf) cmake_sphinx_latexpdf="1" ;;
--sphinx-build=*) cmake_sphinx_build=`cmake_arg "$1"` ;;
--sphinx-flags=*) cmake_sphinx_flags=`cmake_arg "$1"` ;;
--help) cmake_usage ;;
@@ -1066,7 +1084,7 @@ else
fi
# Add Cygwin-specific flags
-if ${cmake_system_cygwin}; then
+if ${cmake_system_cygwin} || ${cmake_system_msys}; then
cmake_ld_flags="${LDFLAGS} -Wl,--enable-auto-import"
fi
@@ -1091,6 +1109,7 @@ cmake_toolchains=''
case "${cmake_system}" in
*AIX*) cmake_toolchains='XL GNU' ;;
*CYGWIN*) cmake_toolchains='GNU' ;;
+ *MSYS*) cmake_toolchains='GNU' ;;
*Darwin*) cmake_toolchains='Clang GNU' ;;
*Linux*) cmake_toolchains='GNU Clang XL PGI PathScale' ;;
*MINGW*) cmake_toolchains='GNU' ;;
@@ -1728,6 +1747,16 @@ if test "x${cmake_ansi_cxx_flags}" != "x"; then
cmake_cxx_flags="${cmake_ansi_cxx_flags} ${cmake_cxx_flags}"
fi
+system_flags=''
+case "${cmake_system}" in
+ # Ensure filesystem access uses 64-bit offsets even on 32-bit hosts.
+ *Linux*) system_flags='-D_FILE_OFFSET_BITS=64' ;;
+esac
+if test "x${system_flags}" != "x"; then
+ cmake_c_flags="${cmake_c_flags} ${system_flags}"
+ cmake_cxx_flags="${cmake_cxx_flags} ${system_flags}"
+fi
+
if test "x${cmake_c_flags}" != "x"; then
cmake_c_flags="${cmake_c_flags} "
fi
@@ -1917,6 +1946,11 @@ if test "x${cmake_sphinx_qthelp}" != "x"; then
set (SPHINX_QTHELP "'"${cmake_sphinx_qthelp}"'" CACHE BOOL "Build qch help with Sphinx" FORCE)
' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
fi
+if test "x${cmake_sphinx_latexpdf}" != "x"; then
+ echo '
+set (SPHINX_LATEXPDF "'"${cmake_sphinx_latexpdf}"'" CACHE BOOL "Build PDF help with Sphinx using LaTeX" FORCE)
+' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
+fi
if test "x${cmake_sphinx_build}" != "x"; then
echo '
set (SPHINX_EXECUTABLE "'"${cmake_sphinx_build}"'" CACHE FILEPATH "Location of Qt sphinx-build" FORCE)